In this case, if there was an opportunity to use await
, then there would be no reason to create a question, but await
is not recommended to be used in contracts:
Note: This feature was designed to be used in debots, in usual contracts use it at your own risk. https://github.com/tonlabs/TON-Solidity-Compiler/blob/master/API.md#synchronous-calls
Pong.sol
pragma ton-solidity ^0.51.0;
contract Pong {
function get(uint b) external responsible returns (uint) {
return b + 1;
}
}
Ping.sol
pragma ton-solidity ^0.51.0;
interface IPong {
function get(uint b) external responsible returns (uint);
}
contract Ping {
uint public result;
uint public tmp;
function run(address pong, uint a) public view returns(uint) {
update(pong, a);
tvm.accept();
return a + tmp;
}
function update(address pong, uint a) internal pure {
IPong(pong).get{callback: Ping.onGet}(a);
}
function onGet(uint b) external {
tvm.accept();
tmp = b;
}
}
Run.bash
#!/usr/bin/env bash
set -o errexit
tondev se reset
rm -fr *.abi.json *.tvc
# Deploy Pong Contract
tondev sol compile Pong.sol
tondev contract deploy Pong --value 1000000000
pongAddress=$(tondev contract info Pong | grep Address | cut -d':' -f3 | cut -d' ' -f1)
echo "$pongAddress"
# Deploy Ping Contract
tondev sol compile Ping.sol
tondev contract deploy Ping --value 1000000000
pingAddress=$(tondev contract info Ping | grep Address | cut -d':' -f3 | cut -d' ' -f1)
echo "$pingAddress"
# Run
tondev contract run Ping run --input "pong:$pongAddress,a:1" | grep value0
# value0:0x0000000000000000000000000000000000000000000000000000000000000001
tondev contract run Ping run --input "pong:$pongAddress,a:1" | grep value0
# value0:0x0000000000000000000000000000000000000000000000000000000000000003
The purpose of the question is to understand how to get the value 3 on the first request, if possible. If not, then a more extensive explanation of how to develop contracts in the conditions of an asynchronous blockchain.
You can do this in asynchronous style more simply (without callback and await).
I changed the code of your contracts:
pragma ton-solidity ^0.51.0;
interface IPing {
function onGet(uint b) external;
}
contract Pong {
function get(uint b) external {
IPing(msg.sender).onGet(b + 1);
}
}
pragma ton-solidity ^0.51.0;
interface IPong {
function get(uint b) external;
}
contract Ping {
uint public tmp;
function run(address pong, uint a) public {
IPong(pong).get(a);
tvm.accept();
tmp = a + tmp;
}
function onGet(uint b) external {
tvm.accept();
tmp = b + tmp;
}
}
Now call a little changed this Run.bash
#!/usr/bin/env bash
set -o errexit
tondev se reset
tondev network default se
rm -fr *.abi.json *.tvc
# Deploy Pong Contract
tondev sol compile Pong.sol
tondev contract deploy Pong --value 1000000000
pongAddress=$(tondev contract info Pong | grep Address | cut -d':' -f3 | cut -d' ' -f1)
echo "$pongAddress"
# Deploy Ping Contract
tondev sol compile Ping.sol
tondev contract deploy Ping --value 1000000000
pingAddress=$(tondev contract info Ping | grep Address | cut -d':' -f3 | cut -d' ' -f1)
echo "$pingAddress"
# Run
tondev contract run Ping run --input "pong:$pongAddress,a:1" &> /dev/null
tondev contract run-local Ping tmp | grep tmp
# tmp:0x0000000000000000000000000000000000000000000000000000000000000003
tondev contract run Ping run --input "pong:$pongAddress,a:1" &> /dev/null
tondev contract run-local Ping tmp | grep tmp
# tmp:0x0000000000000000000000000000000000000000000000000000000000000006
A bit of my philosophy, why it is better: the contracts must works without waiting. So callbacks and awaits, it is not good. Callbacks are very useful in debots, and it can take place there because debots running on your device. But it is another story…