|
| 1 | +--- |
| 2 | +title: Smart Contracts |
| 3 | +--- |
| 4 | + |
| 5 | +Crear un objeto `Contract` para un contrato ya desplegado es bastante sencillo. |
| 6 | + |
| 7 | +```csharp |
| 8 | +Contract contract = new Contract(contractAddress, abi); |
| 9 | +``` |
| 10 | + |
| 11 | +Aunque no es estrictamente necesario, se recomienda <i>encarecidamente</i> proporcionar el ABI del contrato como una cadena al crear un objeto contract. Si no lo hace, no podrá aprovechar completamente nuestra codificación y decodificación ABI. |
| 12 | +Si decide seguir este camino, deberá proporcionar la firma completa de la función (nombre de la función + tipos de parámetros entre paréntesis - por ejemplo, transfer(address,uint256) para el método transfer de ERC20) al llamar a una función o consultar el contrato, y solo recibirá una cadena como respuesta a las consultas. |
| 13 | + |
| 14 | +## Llamar funciones de Smart Contract |
| 15 | +Para llamar a un smart contract, usará el método `CallFunction` para crear un objeto `CallContractFunction`, que determinará el gasPrice, gasLimit, nonce y data apropiados para incluir en un nuevo `EthTransaction` al proporcionarle un cliente y un objeto `ContractCall` al método `Create` async Task |
| 16 | + |
| 17 | +Un ejemplo de cómo llamar a un smart contract sería el siguiente: |
| 18 | + |
| 19 | +```csharp |
| 20 | +Contract erc20Contract = new Contract(contractAddress, contractAbi); // We'll use the well-known ERC20 contract as our example case |
| 21 | +TransactionReceipt receipt = await erc20Contract.CallFunction("transfer", toAddress, amountAsBigInteger).SendTransactionMethodAndWaitForReceipt(wallet, client); |
| 22 | +``` |
| 23 | + |
| 24 | +Nota: si no desea esperar el recibo, puede usar `SendTransactionMethod` en su lugar. |
| 25 | + |
| 26 | +Alternativamente, si solo quiere crear el `EthTransaction` y enviarlo más tarde, puede usar directamente el objeto `CallContractFunction` de `CallFunction`. |
| 27 | + |
| 28 | +```csharp |
| 29 | +Contract erc20Contract = new Contract(contractAddress, contractAbi); // We'll use the well-known ERC20 contract as our example case |
| 30 | +EthTransaction transaction = await erc20Contract.CallFunction("transfer", toAddress, amountAsBigInteger).Create(client, new ContractCall(wallet.GetAddress())); |
| 31 | +TransactionReceipt receipt = await wallet.SendTransactionAndWaitForReceipt(client, transaction); |
| 32 | + |
| 33 | +// or |
| 34 | +CallContractFunction transactionCreator = erc20Contract.CallFunction("transfer", toAddress, amountAsBigInteger); |
| 35 | +EthTransaction transaction = await transactionCreator.Create(client, new ContractCall(wallet.GetAddress())); |
| 36 | +TransactionReceipt receipt = await wallet.SendTransactionAndWaitForReceipt(client, transaction); |
| 37 | + |
| 38 | +// or |
| 39 | +CallContractFunction transactionCreator = erc20Contract.CallFunction("transfer", toAddress, amountAsBigInteger); |
| 40 | +TransactionReceipt receipt = await transactionCreator.SendTransactionMethodAndWaitForReceipt(wallet, client); |
| 41 | +``` |
| 42 | + |
| 43 | +Notará que el método `CallFunction` acepta un número arbitrario de argumentos. Debe proporcionar los argumentos en el orden en que aparecen en el ABI/firma de la función. |
| 44 | + |
| 45 | +## Comprendiendo los mapeos de tipos de datos |
| 46 | +Al interactuar con smart contracts, es importante entender cómo los tipos de datos de EVM se mapean a los tipos de datos de C# en la librería SequenceEthereum. |
| 47 | + |
| 48 | +Por ejemplo, si proporciona una cadena donde el ABI espera un entero, recibirá una excepción, incluso si esa cadena podría convertirse en un entero. |
| 49 | + |
| 50 | +### Address |
| 51 | +En C# puede usar un tipo `string` o crear una instancia de `Address`. Asegúrese de que su cadena sea hexadecimal, |
| 52 | +comience con `0x` y tenga una longitud fija de 42 caracteres. |
| 53 | + |
| 54 | +```csharp |
| 55 | +Address address = new Address("0x123..."); |
| 56 | +``` |
| 57 | + |
| 58 | +### Enteros |
| 59 | +Para tipos de enteros como `int256`, `uint8` o `uint256` use el tipo `BigInteger` de System.Numerics. |
| 60 | + |
| 61 | +```csharp |
| 62 | +// Simple number |
| 63 | +BigInteger number = new BigInteger(10000); |
| 64 | + |
| 65 | +// From hex |
| 66 | +string hexString = "0x0000000...01"; |
| 67 | +BigInteger number = hexString.HexStringToBigInteger(); |
| 68 | +``` |
| 69 | + |
| 70 | +### Bytes |
| 71 | +Para definir tipos de datos byte de Solidity en C#, tiene la opción de crear un `FixedByte` para tipos como `byte16` o `byte32`. |
| 72 | +Cuando su contrato requiera `bytes`, puede convertir cualquier valor en un `byte[]` de cualquier longitud. |
| 73 | + |
| 74 | +Si sus datos están representados como una cadena hexadecimal en C#, asegúrese de usar nuestra función `HexStringToByteArray()` para convertir |
| 75 | +el valor hexadecimal de vuelta al arreglo de bytes original. |
| 76 | + |
| 77 | +Para arreglos de bytes como `byte32[]`, simplemente cree un `FixedByte[]` en C#. |
| 78 | + |
| 79 | +```csharp |
| 80 | +// byte16 or byte32 |
| 81 | +new FixedByte(16, new byte[] {}); |
| 82 | + |
| 83 | +// bytes |
| 84 | +string someString = "abc0123456789"; |
| 85 | +byte[] bytes = someString.ToByteArray(); |
| 86 | + |
| 87 | +// signature |
| 88 | +string signature = "0x0ab123..."; |
| 89 | +byte[] bytes = signature.HexStringToByteArray(); |
| 90 | +``` |
| 91 | + |
| 92 | +### Structs |
| 93 | +Use Tuples para llamar una función on-chain con un struct. Aquí hay un ejemplo de un struct en Solidity y cómo definirlo |
| 94 | +usando el SDK de Unity de Sequence y pasarlo como argumento en una función `Contract.CallFunction`. |
| 95 | + |
| 96 | +Struct de Solidity |
| 97 | + |
| 98 | +```solidity |
| 99 | +struct ExampleStruct { |
| 100 | + address wallet; |
| 101 | + uint256 amount; |
| 102 | + byte32 data; |
| 103 | +} |
| 104 | +``` |
| 105 | + |
| 106 | +Equivalente en C# |
| 107 | + |
| 108 | +```csharp |
| 109 | +Address wallet = new Address("0x..."); |
| 110 | +BigInteger amount = new BigInteger(10000); |
| 111 | +FixedByte data = new FixedByte(32, byteArrayData); |
| 112 | +var arg = new Tuple<Address, BigInteger, FixedByte>(wallet, amount, data); |
| 113 | +``` |
| 114 | + |
| 115 | +### Otros tipos |
| 116 | +Para tipos de datos tradicionales en Solidity como `string` o `bool`, puede usar los mismos tipos de datos en C#. |
| 117 | + |
| 118 | +### Tipos de retorno |
| 119 | +Cuando lea datos de un smart contract y utilice la función `Contract.SendQuery<TType>()`, puede usar TType para tipos de retorno simples como `string`, `BigInteger` o `bool`. Para tipos de retorno complejos como structs, use un `object[]` y analice manualmente los valores en su struct de C#. |
| 120 | + |
| 121 | +```csharp |
| 122 | +// Let's consider a struct with the following variables: SomeStruct { address value1; uint256 value2; } |
| 123 | +object[] structValues = Contract.SendQuery<object[]>("SomeFunction"); |
| 124 | + |
| 125 | +SomeStruct newStruct = new SomeStruct() { |
| 126 | + Value1 = new Address(structValues[0].ToString()), |
| 127 | + Value2 = BigInteger.Parse(structValues[1].ToString()) |
| 128 | +} |
| 129 | +``` |
| 130 | + |
| 131 | +## Consultar contratos |
| 132 | +Para consultar un smart contract (leer datos), use el método `SendQuery<T>` para consultar el contrato y devolver el resultado como tipo T (si es posible). |
| 133 | +Un ejemplo de cómo consultar un smart contract sería: |
| 134 | + |
| 135 | +```csharp |
| 136 | +Contract erc20Contract = new Contract(contractAddress, contractAbi); // We'll use the well-known ERC20 contract as our example case |
| 137 | +BigIntegar balance = await erc20Contract.SendQuery<BigIntegar>(client, "balanceOf", address); |
| 138 | +``` |
| 139 | + |
| 140 | +Alternativamente, si desea simplemente construir la consulta y enviarla más tarde, puede usar `QueryContract<T>` para crear un delegado. |
| 141 | + |
| 142 | +```csharp |
| 143 | +Contract erc20Contract = new Contract(contractAddress, contractAbi); // We'll use the well-known ERC20 contract as our example case |
| 144 | +QueryContractMessageSender<BigIntegar> balanceQuery = erc20Contract.QueryContract<BigIntegar>("balanceOf", address); |
| 145 | +BigIntegar balance = await balanceQuery(client); |
| 146 | +// or |
| 147 | +BigIntegar balance = await balanceQuery.SendQuery(client); |
| 148 | +``` |
| 149 | + |
| 150 | +## Desplegar contratos |
| 151 | +Si desea desplegar un contrato, puede usar el `ContractDeployer` |
| 152 | + |
| 153 | +```csharp |
| 154 | +ContractDeploymentResult deploymentResult = await ContractDeployer.Deploy(client, wallet, contractBytecodeAsString); |
| 155 | +string newlyDeployedContractAddress = deploymentResult.Receipt.contractAddress; |
| 156 | +``` |
0 commit comments