Skip to content

Commit

Permalink
Update 'Work with custom contracts' page for Tezos
Browse files Browse the repository at this point in the history
Signed-off-by: Dzianis Andreyenka <[email protected]>
  • Loading branch information
denisandreenko committed Jan 8, 2024
1 parent bebc389 commit b31c98d
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 170 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
253 changes: 83 additions & 170 deletions docs/tutorials/custom_contracts/tezos.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,34 @@ import smartpy as sp
@sp.module
def main():
# Declares a new contract
class SimpleStorage(sp.Contract):
# Storage. Persists in between transactions
def __init__(self, value):
self.data.storedValue = value
self.data.x = value
# Allows the stored integer to be changed
@sp.entrypoint
def replace(self, params):
self.data.storedValue = params.value
def set(self, params):
self.data.x = params.value
# Returns the currently stored integer
@sp.onchain_view()
def get(self):
return self.data.x
@sp.add_test(name="SimpleStorage")
def test():
c1 = main.SimpleStorage(12)
# Initialize the contract
c = main.SimpleStorage(12)
# Create a test scenario and run some test cases
scenario = sp.test_scenario(main)
scenario.h1("SimpleStorage")
scenario += c1
c1.replace(value=15)
scenario.verify(c1.data.storedValue == 15)
scenario += c
c.set(value=15)
scenario.verify(c.data.x == 15)
scenario.verify(scenario.compute(c.get()) == 15)
```

## Contract deployment
Expand All @@ -71,7 +83,7 @@ To deploy the contract, we will use [SmartPy IDE](https://smartpy.io/ide).
![ContractDeployment](images/tezos_contract_deployment.png)
![ContractDeployment2](images/tezos_contract_deployment2.png)

Here we can see that our new contract address is `KT1D254HTPKq5GZNVcF73XBinG9BLybHqu8s`. This is the address that we will reference in the rest of this guide.
Here we can see that our new contract address is `KT1ED4gj2xZnp8318yxa5NpvyvW15pqe4yFg`. This is the address that we will reference in the rest of this guide.

## The FireFly Interface Format

Expand Down Expand Up @@ -342,7 +354,7 @@ We will use the FFI JSON constructed above and `POST` that to the `/contracts/in
"description": "",
"methods": [
{
"name": "replace",
"name": "set",
"pathname": "",
"description": "",
"params": [
Expand All @@ -358,6 +370,13 @@ We will use the FFI JSON constructed above and `POST` that to the `/contracts/in
}
],
"returns": []
},
{
"name": "get",
"pathname": "",
"description": "",
"params": [],
"returns": []
}
],
"events": []
Expand All @@ -368,34 +387,44 @@ We will use the FFI JSON constructed above and `POST` that to the `/contracts/in

```json
{
"id": "c655704a-f0e2-4aa3-adbb-c7bf3280cdc2",
"namespace": "default",
"name": "simplestorage",
"description": "",
"version": "v1.0.0",
"methods": [
{
"id": "6f707105-d8b5-4808-a864-51475086608d",
"interface": "c655704a-f0e2-4aa3-adbb-c7bf3280cdc2",
"name": "replace",
"namespace": "default",
"pathname": "replace",
"description": "",
"params": [
"id": "f9e34787-e634-46cd-af47-b52c537404ff",
"namespace": "default",
"name": "simplestorage",
"description": "",
"version": "v1.0.0",
"methods": [
{
"id": "78f13a7f-7b85-47c3-bf51-346a9858c027",
"interface": "f9e34787-e634-46cd-af47-b52c537404ff",
"name": "set",
"namespace": "default",
"pathname": "set",
"description": "",
"params": [
{
"name": "newValue",
"schema": {
"type": "integer",
"details": {
"type": "integer",
"internalType": "integer"
}
}
}
],
"returns": []
},
{
"name": "newValue",
"schema": {
"type": "integer",
"details": {
"type": "integer",
"internalType": "integer"
}
}
"id": "ee864e25-c3f7-42d3-aefd-a82f753e9002",
"interface": "f9e34787-e634-46cd-af47-b52c537404ff",
"name": "get",
"namespace": "tezos",
"pathname": "get",
"description": "",
"params": [],
"returns": []
}
],
"returns": []
}
]
]
}
```

Expand Down Expand Up @@ -424,10 +453,10 @@ We need to copy the `id` field we got in the response from the previous step to
{
"name": "simple-storage",
"interface": {
"id": "c655704a-f0e2-4aa3-adbb-c7bf3280cdc2"
"id": "f9e34787-e634-46cd-af47-b52c537404ff"
},
"location": {
"address": "KT1D254HTPKq5GZNVcF73XBinG9BLybHqu8s"
"address": "KT1ED4gj2xZnp8318yxa5NpvyvW15pqe4yFg"
}
}
```
Expand All @@ -439,10 +468,10 @@ We need to copy the `id` field we got in the response from the previous step to
"id": "af09de97-741d-4f61-8d30-4db5e7460f76",
"namespace": "default",
"interface": {
"id": "c655704a-f0e2-4aa3-adbb-c7bf3280cdc2"
"id": "f9e34787-e634-46cd-af47-b52c537404ff"
},
"location": {
"address": "KT1D254HTPKq5GZNVcF73XBinG9BLybHqu8s"
"address": "KT1ED4gj2xZnp8318yxa5NpvyvW15pqe4yFg"
},
"name": "simple-storage",
"urls": {
Expand All @@ -460,167 +489,51 @@ You'll notice in the response body that there are a couple of URLs near the bott

## Invoke the smart contract

Now that we've got everything set up, it's time to use our smart contract! We're going to make a `POST` request to the `invoke/replace` endpoint to set the integer value on-chain. Let's set it to the value of `3` right now.
Now that we've got everything set up, it's time to use our smart contract! We're going to make a `POST` request to the `invoke/set` endpoint to set the integer value on-chain. Let's set it to the value of `3` right now.

### Request

`POST` `http://localhost:5000/api/v1/namespaces/default/apis/simple-storage/invoke/replace`
`POST` `http://localhost:5000/api/v1/namespaces/default/apis/simple-storage/invoke/set`

```json
{
"input": {
"newValue": 3
},
"key": "tz1cuFw1E2Mn2bVS8q8d7QoCb6FXC18JivSp"
}
}
```

> **NOTE**: The `key` field (optional) is the tezos account's address, which is used to sign blockchain transactions.\
See more at [transaction signing service set up](../chains/tezos_testnet.md#signatory).

### Response

```json
{
"id": "cb38a538-7093-4150-8a80-6097a666df82",
"namespace": "default",
"tx": "5860befb-9f76-4aa0-a67c-55718b2c46d6",
"id": "87c7ee1b-33d1-46e2-b3f5-8566c14367cf",
"type": "blockchain_invoke",
"status": "Pending",
"plugin": "tezos",
"input": {
"input": {
"newValue": 3
},
"interface": "c655704a-f0e2-4aa3-adbb-c7bf3280cdc2",
"key": "tz1cuFw1E2Mn2bVS8q8d7QoCb6FXC18JivSp",
"location": {
"address": "KT1D254HTPKq5GZNVcF73XBinG9BLybHqu8s"
},
"method": {
"description": "",
"id": "6f707105-d8b5-4808-a864-51475086608d",
"interface": "c655704a-f0e2-4aa3-adbb-c7bf3280cdc2",
"name": "replace",
"namespace": "default",
"params": [
{
"name": "newValue",
"schema": {
"details": {
"internalType": "integer",
"type": "integer"
},
"type": "integer"
}
}
],
"pathname": "replace",
"returns": []
},
"methodPath": "replace",
"options": null,
"type": "invoke"
},
"created": "2023-09-27T09:12:24.033724927Z",
"updated": "2023-09-27T09:12:24.033724927Z"
"..."
}
```

You'll notice that we got an ID back with status `Pending`, and that's expected due to the asynchronous programming model of working with custom onchain logic in FireFly. After a while, let's see the result of our operation.
You'll notice that we got an ID back with status `Pending`, and that's expected due to the asynchronous programming model of working with smart contracts in FireFly. To see what the value is now, we can query the smart contract.

## Get the operation result
## Query the current value

To see the result of the operation, call `/operations` endpoint with the operation ID from the previous step.
To make a read-only request to the blockchain to check the current value of the stored integer, we can make a `POST` to the `query/get` endpoint.

### Request

`GET` `http://localhost:5000/api/v1/operations/cb38a538-7093-4150-8a80-6097a666df82?fetchstatus=true`
`POST` `http://localhost:5000/api/v1/namespaces/default/apis/simple-storage/query/get`

```json
{}
```

### Response

```json
{
"id": "cb38a538-7093-4150-8a80-6097a666df82",
"namespace": "default",
"tx": "5860befb-9f76-4aa0-a67c-55718b2c46d6",
"type": "blockchain_invoke",
"status": "Succeeded",
"plugin": "tezos",
"input": {
"input": {
"newValue": 3
},
"interface": "c655704a-f0e2-4aa3-adbb-c7bf3280cdc2",
"key": "tz1cuFw1E2Mn2bVS8q8d7QoCb6FXC18JivSp",
"location": {
"address": "KT1D254HTPKq5GZNVcF73XBinG9BLybHqu8s"
},
"method": {
"description": "",
"id": "6f707105-d8b5-4808-a864-51475086608d",
"interface": "c655704a-f0e2-4aa3-adbb-c7bf3280cdc2",
"name": "replace",
"namespace": "default",
"params": [
{
"name": "newValue",
"schema": {
"details": {
"internalType": "integer",
"type": "integer"
},
"type": "integer"
}
}
],
"pathname": "replace",
"returns": []
},
"methodPath": "replace",
"options": null,
"type": "invoke"
},
"output": {
"contractLocation": {
"address": "KT1D254HTPKq5GZNVcF73XBinG9BLybHqu8s"
},
"headers": {
"requestId": "default:cb38a538-7093-4150-8a80-6097a666df82",
"type": "TransactionSuccess"
},
"protocolId": "PtNairobiyssHuh87hEhfVBGCVrK3WnS8Z2FT4ymB5tAa4r1nQf",
"transactionHash": "opMjGX58akxboipsxMcTv5yc5M4Y2ZCGktos4E26zgEpgtHop7g"
},
"detail": {
"receipt": {
"blockHash": "BLy9BdEjBvHvhYkt8tR4wTQzHagCUmweh8K8uM6X5gXzPLbCmzP",
"blockNumber": "4012016",
"contractLocation": {
"address": "KT1D254HTPKq5GZNVcF73XBinG9BLybHqu8s"
},
"extraInfo": [
{
"consumedGas": "1279",
"contractAddress": "KT1D254HTPKq5GZNVcF73XBinG9BLybHqu8s",
"counter": "18602183",
"errorMessage": null,
"fee": "404",
"from": "tz1cuFw1E2Mn2bVS8q8d7QoCb6FXC18JivSp",
"gasLimit": "1380",
"paidStorageSizeDiff": "0",
"status": "applied",
"storage": "3",
"to": "KT1D254HTPKq5GZNVcF73XBinG9BLybHqu8s"
}
],
"protocolId": "PtNairobiyssHuh87hEhfVBGCVrK3WnS8Z2FT4ymB5tAa4r1nQf",
"success": true,
"transactionIndex": "0"
},
"status": "Succeeded"
}
"3"
}
```

Here we can see `detail.receipt.extraInfo.storage` section, which displays the latest state of the contract storage state after invoking the operation and that the value of the `storage` variable was changed to `3`.
> **NOTE:** Some contracts may have queries that require input parameters. That's why the query endpoint is a `POST`, rather than a `GET` so that parameters can be passed as JSON in the request body. This particular function does not have any parameters, so we just pass an empty JSON object.

0 comments on commit b31c98d

Please sign in to comment.