<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: SanchezDario</title>
    <description>The latest articles on DEV Community by SanchezDario (@sanchezdario).</description>
    <link>https://dev.to/sanchezdario</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F724318%2Faeb7a392-a064-4217-8b84-a132f8e019de.png</url>
      <title>DEV Community: SanchezDario</title>
      <link>https://dev.to/sanchezdario</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sanchezdario"/>
    <language>en</language>
    <item>
      <title>Cross-Contract Calls in Near Protocol</title>
      <dc:creator>SanchezDario</dc:creator>
      <pubDate>Sat, 12 Feb 2022 22:16:35 +0000</pubDate>
      <link>https://dev.to/sanchezdario/cross-contract-calls-in-near-protocol-51f1</link>
      <guid>https://dev.to/sanchezdario/cross-contract-calls-in-near-protocol-51f1</guid>
      <description>&lt;p&gt;&lt;strong&gt;Initial clarifications:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The following article is focused on the development of smart contracts using Rust.&lt;/li&gt;
&lt;li&gt;Although the examples are developed in NEAR, much of the following information can be transposed to any other blockhain where it can be developed using Rust.&lt;/li&gt;
&lt;li&gt;The examples are taken from the following repository: &lt;a href="https://github.com/NEAR-Hispano/mkt-servicios-profesionales"&gt;BlockJobs-Marketplace&lt;/a&gt;, where several cross-contract calls can be seen in addition to those used below.&lt;/li&gt;
&lt;li&gt;This article shows a cross-contract call from a professional services marketplace, to the DAI contract, to allow payments for services in DAI or others fungible tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Introduction:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are various reasons for requiring calls between contracts, such as requesting and/or modifying information, using code from a third-party contract without copying it, transferring tokens, etc. and this can be done by working in a similar way to how API calls work.&lt;br&gt;
An example of this is shown below, providing a contextual explanation of how a cross-contract call works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1- Calling contract&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To be able to call an external function, the first thing to do is to indicate to our contract what information the function that will be called requires, specifying parameters with their respective data types (in several contracts it is seen that &lt;code&gt;&amp;amp;self&lt;/code&gt; is added and the type of data to return, but this can be omitted). For this you must first import &lt;code&gt;near_sdk::ext_contract&lt;/code&gt; and implement it as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use near_sdk::ext_contract;

impl Contract {
   …
}

#[ext_contract(ext_contract)]
trait ExtContract {
fn ft_transfer(&amp;amp;mut self, receiver_id: AccountId, amount: U128, memo: Option&amp;lt;String&amp;gt;);
}
#[ext_contract(ext_self)]
pub trait ExtSelf {
    fn on_buy_service(service_id: u64) -&amp;gt; Service;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The 'ext_contract' in parentheses is the name that is being given and will then be used to indicate which trait is being called, since more than one can be set in order to have a better order.&lt;/li&gt;
&lt;li&gt;'ExtContract' is a name that is not required later, that is, it is indifferent.&lt;/li&gt;
&lt;li&gt;If the function that is called or not, is public, it is also indifferent, placing 'ft' is enough.&lt;/li&gt;
&lt;li&gt;The name of the function and the parameters must be exactly the same as those of the contract that is called, in the event of any typing error we will receive an "insufficient gas amount" error.&lt;/li&gt;
&lt;li&gt;The trait ExtSelf will be explained later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;1.1 - Make the call&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Within the corresponding function, the call is made as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ext_contract::ft_transfer(
   self.contract_me.clone(),
   service.metadata.price.into(),
   None,
   &amp;amp;token, 
   ONE_YOCTO, 
   GAS_FT_TRANSFER
).then(ext_self::on_buy_service(
   service_id,
   &amp;amp;env::current_account_id(), 
   NO_DEPOSIT, 
   BASE_GAS)
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ft_transfer&lt;/code&gt; is being called passing first the 3 corresponding parameters, then the address of the contract (the DAI address must be passed in this case, which is assigned to &lt;code&gt;token&lt;/code&gt;), then the amount of NEAR attached to the in the case of a payable type function and finally the amount of gas, a topic that will be expanded on later. The order of the parameters must be strictly respected, otherwise it will fail and the compiler does not always show an error.&lt;/li&gt;
&lt;li&gt;The deposit and the gas are in this case assigned in constants, but the numerical value can also be specified directly.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;then&lt;/code&gt; method can be omitted, it is used in the case of wanting to execute a second function depending on what the called function returns, this is shown in more detail below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;1.2 - Call back&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A second function can be created in the contract that makes the call, which, based on what is returned, executes certain actions. It is not strictly necessary but it is normally called with an on preceding the name of the first function, in the example case the function from which it is initially called is &lt;code&gt;buy_service&lt;/code&gt;, so now the name will be &lt;code&gt;on_buy_service&lt;/code&gt; and is given by the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub fn on_buy_service(&amp;amp;mut self, service_id: u64) -&amp;gt; Service {
  match env::promise_result(0) {
      PromiseResult::Successful(_data) =&amp;gt; {
          service.sold = true;
          service.on_sale = false;
          self.service_by_id.insert(&amp;amp;service_id, &amp;amp;service);
          return service;
      }
      PromiseResult::Failed =&amp;gt; env::panic(b"Callback faild"),
      PromiseResult::NotReady =&amp;gt; env::panic(b"Callback faild"),
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In the event of an error in the call, a panic type error is executed with the message "Callback failed", if the call has been executed correctly, the code that modifies the state of the contract that initially calls is executed (this could done directly in the first function without the &lt;code&gt;then&lt;/code&gt; method, but this is good practice.&lt;/li&gt;
&lt;li&gt;In this case, the value that is returned is not being used, which is why the &lt;code&gt;data&lt;/code&gt; parameter has a "_" in front of it, preventing a warning from being issued, but this value could be necessary for the status modification.&lt;/li&gt;
&lt;li&gt;In the initially shared repository you can also see examples where this is omitted.&lt;/li&gt;
&lt;li&gt;Although it is not used in this example, it can be useful to return a promise, for which &lt;code&gt;near_sdk::PromiseOrValue&lt;/code&gt; must be imported, in this &lt;a href="https://docs.rs/near-sdk/%202.0.0/near_sdk/enum.PromiseOrValue.html"&gt;link&lt;/a&gt; expands on this topic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2 - Called contract&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The called contract can be one of its own or another, it is only necessary to know the address and the method to call with its parameters.&lt;br&gt;
In the example case, the transfer function of the DAI contract is being called, so if the transfer is executed correctly, &lt;code&gt;on_buy_service&lt;/code&gt; is subsequently executed and the status modified as indicated. However, the returned value could be other data such as a boolean for example and from this modify the information. In the example code you can see this by going to the &lt;code&gt;validate_user&lt;/code&gt; and &lt;code&gt;validate_tokens&lt;/code&gt; functions, both of which are in the &lt;code&gt;mediator.rs&lt;/code&gt; contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3 - Gas Management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most common error is "Insufficient gas amount", which can be due to an insufficient amount of gas set or attached, but also due to an error that prevents the called function from finishing executing and returning a result. In the event that this happens, it may be a good idea to issue logs at the beginning and end of each function to see how far the execution is carried out and also to comment the code where state changes are made to verify if the problem is in the call or in the internal code of some of the functions.&lt;br&gt;
If the error is not found by performing the aforementioned, it may be that an amount of gas greater than the maximum supported by Near, which is 300 Tgas, is being established, if in the example 200 Tgas had been passed as a parameter to execute &lt;code&gt;ft_transfer&lt;/code&gt; and 120 Tgas for &lt;code&gt;on_buy_service&lt;/code&gt;, those 300 would never be enough, or in the case of working on testnet, it may be that not enough gas is being attached. For testing it may be advisable to specify the maximum amount of gas by adding &lt;code&gt;--gas 300000000000000&lt;/code&gt; to the end of the function call. Then the remaining gas is returned to the person who signs the transaction, but if you prefer this value can be adjusted by seeing how much gas is consumed, it is advisable to always indicate a higher amount, perhaps twice as much to ensure that it is not insufficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final clarifications&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remember that it is advisable to write tests for the functions and the calls between contracts that are made.&lt;/li&gt;
&lt;li&gt;To view information pertaining to gas usage and the values ​​returned by the functions, you can use &lt;a href="https://explorer.near.org/"&gt;Near Explorer&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For questions, we recommend &lt;a href="https://stackoverflow.com/questions/tagged/nearprotocol"&gt;StackOverflow&lt;/a&gt;, or the &lt;a href="https://t.me/neardev"&gt;Telegram channel for devs&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this information has been useful to you.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>near</category>
      <category>tutorial</category>
      <category>contract</category>
    </item>
    <item>
      <title>Cross-Contract Calls en Near Protocol</title>
      <dc:creator>SanchezDario</dc:creator>
      <pubDate>Sat, 12 Feb 2022 21:49:19 +0000</pubDate>
      <link>https://dev.to/sanchezdario/cross-contract-calls-en-near-protocol-2ljg</link>
      <guid>https://dev.to/sanchezdario/cross-contract-calls-en-near-protocol-2ljg</guid>
      <description>&lt;p&gt;&lt;strong&gt;Aclaraciones iniciales:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El siguiente artículo está enfocado en el desarrollo de contratos inteligentes usando Rust.&lt;/li&gt;
&lt;li&gt;Si bien los ejemplos están desarrollados en NEAR, gran parte de la siguiente información se puede transpolar a cualquier otra blockhain donde se pueda desarrollar usando Rust.&lt;/li&gt;
&lt;li&gt;Los ejemplos son extraídos del siguiente repositorio: &lt;a href="https://github.com/NEAR-Hispano/mkt-servicios-profesionales"&gt;BlockJobs-Marketplace&lt;/a&gt;, donde se pueden observar varias cross-contract calls además de las utilizadas a continuación.&lt;/li&gt;
&lt;li&gt;En este artículo se muestra una cross-contract call desde un marketplace de servicios profesionales, al contrato de DAI, para permitir realizar los pagos de los servicios en DAI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Introducción:&lt;/strong&gt;&lt;br&gt;
Existen diversos motivos para requerir hacer llamadas entre contratos, como solicitar y/o modificar información, utilizar código de un contrato ajeno sin copiarlo, transferir tokens, etc. y esto se puede hacer trabajando de una forma similar a como funcionan las llamadas a una API.&lt;br&gt;
A continuación se muestra un ejemplo de esto, brindando una explicación contextual de como una cross-contract call funciona.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1- Contrato que llama&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para poder llamar una función externa lo primero que se debe hacer es indicar a nuestro contrato qué información requiere la función que será llamada, especificando parámetros con sus respectivos tipos de datos (en varios contratos se ve que se agrega &lt;code&gt;&amp;amp;self&lt;/code&gt;y el tipo de dato a retornar, pero esto se puede omitir). Para esto primeramente se debe importar &lt;code&gt;near_sdk::ext_contract&lt;/code&gt; e implementarlo como se muestra a continuación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use near_sdk::ext_contract;

impl Contract {
   …
}

#[ext_contract(ext_contract)]
trait ExtContract {
fn ft_transfer(&amp;amp;mut self, receiver_id: AccountId, amount: U128, memo: Option&amp;lt;String&amp;gt;);
}
#[ext_contract(ext_self)]
pub trait ExtSelf {
    fn on_buy_service(service_id: u64) -&amp;gt; Service;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;El 'ext_contract' entre paréntesis es el nombre que se le está dando y luego se utilizará para indicar qué trait se está llamando, ya que se puede establecer más de uno con el fin de tener un mejor orden.&lt;/li&gt;
&lt;li&gt;'ExtContract' es una denominación que no se requiere posteriormente, es decir que es indiferente.&lt;/li&gt;
&lt;li&gt;Si la función que es llamada o no, es pública, es también indiferente, con colocar 'ft' es suficiente.&lt;/li&gt;
&lt;li&gt;El nombre de la función y los parámetros deben ser exactamente iguales a los del contrato que es llamado, ante cualquier error de tipeado recibiremos un error de "insufficient gas amount".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;1.1 - Hacer el llamado&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dentro de la función correspondiente, el llamado se realiza de la siguiente forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ext_contract::ft_transfer(
   self.contract_me.clone(),
   service.metadata.price.into(),
   None,
   &amp;amp;token, 
   ONE_YOCTO, 
   GAS_FT_TRANSFER
).then(ext_self::on_buy_service(
   service_id,
   &amp;amp;env::current_account_id(), 
   NO_DEPOSIT, 
   BASE_GAS)
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Se está llamando a &lt;code&gt;ft_transfer&lt;/code&gt; pasando primeramente los 3 parámetros correspondientes, luego la dirección del contrato (se debe pasar la dirección de DAI en este caso, la cual está asignada a &lt;code&gt;token&lt;/code&gt;), luego la cantidad de NEAR adjunto para el caso de tratarse de una función de tipo payable y finalmente la cantidad de gas, tema que será ampliado más adelante. El orden de los parámetros debe ser estrictamente respetado, de lo contrario fallará y no siempre el compilador muestra error.&lt;/li&gt;
&lt;li&gt;El depósito y el gas están en este caso asignados en constantes, pero puede también especificarse el valor numérico directamente.&lt;/li&gt;
&lt;li&gt;El método &lt;code&gt;then&lt;/code&gt; puede omitirse, se utiliza en el caso de querer ejecutar una segunda función según lo que retorne la función que se está llamando, esto se muestra con mayor detalle a continuación.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;1.2 - Call-back&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se puede crear una segunda función en el contrato que realiza la llamada, la cual a partir de lo que se retorna ejecute determinadas acciones. No es estrictamente necesario pero normalmente se le denomina con un on predecediendo al nombre la primer función, en el caso de ejemplo la función desde donde se llama inicialmente es &lt;code&gt;buy_service&lt;/code&gt;por lo que ahora la denominación será &lt;code&gt;on_buy_service&lt;/code&gt; y está dada por el siguiente código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub fn on_buy_service(&amp;amp;mut self, service_id: u64) -&amp;gt; Service {
  match env::promise_result(0) {
      PromiseResult::Successful(_data) =&amp;gt; {
          service.sold = true;
          service.on_sale = false;
          self.service_by_id.insert(&amp;amp;service_id, &amp;amp;service);
          return service;
      }
      PromiseResult::Failed =&amp;gt; env::panic(b"Callback faild"),
      PromiseResult::NotReady =&amp;gt; env::panic(b"Callback faild"),
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;En el caso de haber un error en el llamado se ejecuta un error de tipo panic con el mensaje "Callback faild", en caso de haberse ejecutado correctamente la llamada se ejecuta el código que modifica el estado del contrato que llama inicialmente (esto podría hacerse directamente en el primer función prescindiendo del método &lt;code&gt;then&lt;/code&gt;, pero se trata de una buena práctica.&lt;/li&gt;
&lt;li&gt;En este caso no se está haciendo uso del valor que se retorna, por esto es que la parámentro &lt;code&gt;data&lt;/code&gt; tiene un "_" antepuesto, evitando que se emita un warning, pero podría ser necesario dicho valor para la modificación de estado.&lt;/li&gt;
&lt;li&gt;En el repositorio compartido inicialmente se pueden ver también ejemplos donde se omite esto.&lt;/li&gt;
&lt;li&gt;Si bien no se hace uso en este ejemplo, puede ser útil el retornar una promesa, para lo cual se debe importar &lt;code&gt;near_sdk::PromiseOrValue&lt;/code&gt;, en este &lt;a href="https://docs.rs/near-sdk/2.0.0/near_sdk/enum.PromiseOrValue.html"&gt;link&lt;/a&gt; se amplía este tema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2 - Contrato que es llamado&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El contrato que se llama puede tratarse tanto de uno propio como uno ajeno, tan solo es necesario conocer la dirección y el método a llamar con sus parámetros.&lt;br&gt;
En el caso de ejemplo se está llamando a la función para transferir del contrato de DAI, por lo tanto si la transferencia se ejecuta correctamente, se ejecuta posteriormente &lt;code&gt;on_buy_service&lt;/code&gt; y modificado el estado según se le indique. Sin embargo el valor retornado podría tratarse de otros datos como un booleano por ejemplo y a partir de este modificar la información. En el código de ejemplo se puede observar esto yendo a la función &lt;code&gt;validate_user&lt;/code&gt; y &lt;code&gt;validate_tokens&lt;/code&gt;, las cuales se encuentran en el contrato &lt;code&gt;mediator.rs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3 - Manejo del gas&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El error más común es el de "Insufficient gas amount", el cual puede deberse a una insuficiente cantidad de gas establecido o adjuntado, pero también a un error que evite que la función llamada termine de ejecutarse y retornar un resultado. En el caso de suceder esto puede ser buena idea el emitir logs al principio y al final de cada función para ver hasta donde se realiza la ejecución y también el comentar el código donde se realiza cambios de estado para verificar si el problema está en la llamada o en el código interno de alguna de las funciones.&lt;br&gt;
Si el error no se encuentra realizando lo antes mencionado , puede ser que se esté estableciendo una cantidad de gas mayor a la máxima soportada por Near que es de 300 Tgas, si en el ejemplo se hubiese pasado como parámetro 200 Tgas para ejecutar &lt;code&gt;ft_transfer&lt;/code&gt;y 120 Tgas para &lt;code&gt;on_buy_service&lt;/code&gt;, esos 300 Tgas nunca serían suficientes, o en el caso de trabajar en testnet, puede ser que no se esté adjuntando el gas suficiente. Para hacer pruebas puede ser recomendable especificar la cantidad máxima de gas agregando &lt;code&gt;--gas 300000000000000&lt;/code&gt; al final del llamado a la función. Luego el gas sobrante se devuelve a quien firma la transacción, pero si se prefiere este valor puede ajustarse viendo cuánto gas se consume, es recomendable indicar siempre una cantidad mayor, quizás el doble para asegurarse de que no sea insuficiente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aclaraciones finales&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recuerde que es recomendable escribir test para las funciones y las llamadas entre contratos que se realicen.&lt;/li&gt;
&lt;li&gt;Para ver información pertinente al uso de gas y los valores retornados por las funciones puede utilizar &lt;a href="https://explorer.near.org/"&gt;Near Explorer&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Para dudas se recomienda &lt;a href="https://stackoverflow.com/questions/tagged/nearprotocol"&gt;StackOverflow&lt;/a&gt;, o el &lt;a href="https://t.me/neardev"&gt;canal de telegram para devs&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Espero esta información le haya sido de utilidad.&lt;/p&gt;

</description>
      <category>near</category>
      <category>tutorial</category>
      <category>contract</category>
      <category>rust</category>
    </item>
  </channel>
</rss>
