diff --git a/src/main/kotlin/ee/nx01/tonclient/TonClient.kt b/src/main/kotlin/ee/nx01/tonclient/TonClient.kt index 7574bbb..89374c7 100644 --- a/src/main/kotlin/ee/nx01/tonclient/TonClient.kt +++ b/src/main/kotlin/ee/nx01/tonclient/TonClient.kt @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonCreator import ee.nx01.tonclient.abi.AbiModule import ee.nx01.tonclient.boc.BocModule import ee.nx01.tonclient.crypto.CryptoModule +import ee.nx01.tonclient.debot.DeBotModule import ee.nx01.tonclient.net.NetModule import ee.nx01.tonclient.process.ProcessModule import ee.nx01.tonclient.tvm.TvmModule @@ -27,6 +28,7 @@ class TonClient(val config: TonClientConfig = TonClientConfig()) { val processing = ProcessModule(this) val boc = BocModule(this) val utils = UtilsModule(this) + val debot = DeBotModule(this) init { val result = TONSDKJsonApi.createContext(JsonUtils.write(config)) @@ -128,6 +130,8 @@ enum class TonResponseType(val code: Int) { Success(0), Error(1), Nop(2), + AppRequest(3), + AppNotify(4), Custom(100); companion object { diff --git a/src/main/kotlin/ee/nx01/tonclient/debot/AppDebotBrowser.kt b/src/main/kotlin/ee/nx01/tonclient/debot/AppDebotBrowser.kt new file mode 100644 index 0000000..20b0fc2 --- /dev/null +++ b/src/main/kotlin/ee/nx01/tonclient/debot/AppDebotBrowser.kt @@ -0,0 +1,13 @@ +package ee.nx01.tonclient.debot + +interface AppDebotBrowser { + fun log(params: ParamsOfAppDebotBrowserLog) + fun switch(params: ParamsOfAppDebotBrowserSwitch) + fun switchCompleted() + fun showAction(params: ParamsOfAppDebotBrowserShowAction) + fun input(params: ParamsOfAppDebotBrowserInput): ResultOfAppDebotBrowserInput + fun getSigningBox(): ResultOfAppDebotBrowserGetSigningBox + fun invokeDebot(params: ParamsOfAppDebotBrowserInvokeDebot) + fun send(params: ParamsOfAppDebotBrowserSend) + fun approve(params: ParamsOfAppDebotBrowserApprove): ResultOfAppDebotBrowserApprove +} \ No newline at end of file diff --git a/src/main/kotlin/ee/nx01/tonclient/debot/DeBotModule.kt b/src/main/kotlin/ee/nx01/tonclient/debot/DeBotModule.kt new file mode 100644 index 0000000..f334fcc --- /dev/null +++ b/src/main/kotlin/ee/nx01/tonclient/debot/DeBotModule.kt @@ -0,0 +1,75 @@ +package ee.nx01.tonclient.debot + +import ee.nx01.tonclient.JsonUtils +import ee.nx01.tonclient.TonClient + +/** + * Module for working with debot. + */ +class DeBotModule(private val tonClient: TonClient) { + + /** + * Downloads debot smart contract (code and data) from blockchain and creates an instance of Debot Engine for it. + */ + suspend fun init(params: ParamsOfInit, onResult: (result: ParamsOfAppDebotBrowser) -> Unit): RegisteredDebot { + return tonClient.request("debot.init", params) { + onResult(JsonUtils.read(it)) + } + } + + /** + * Starts the DeBot. + + Downloads debot smart contract from blockchain and switches it to + context zero. + + This function must be used by Debot Browser to start a dialog with debot. + While the function is executing, several Browser Callbacks can be called, + since the debot tries to display all actions from the context 0 to the user. + + When the debot starts SDK registers `BrowserCallbacks` AppObject. + Therefore when `debote.remove` is called the debot is being deleted and the callback is called + with `finish`=`true` which indicates that it will never be used again. + + */ + suspend fun start(params: ParamsOfStart) { + return tonClient.request("debot.start", params) + } + + /** + * Fetches DeBot metadata from blockchain. + * + * Downloads DeBot from blockchain and creates and fetches its metadata. + */ + suspend fun fetch(params: ParamsOfFetch): ResultOfFetch { + return tonClient.request("debot.fetch", params) + } + + /** + * Executes debot action. + * Calls debot engine referenced by debot handle to execute input action. + * Calls Debot Browser Callbacks if needed. + * # Remarks + * Chain of actions can be executed if input action generates a list of subactions. + */ + suspend fun execute(params: ParamsOfExecute) { + return tonClient.request("debot.execute", params) + } + + /** + * Sends message to Debot. + * Used by Debot Browser to send response on Dinterface call or from other Debots. + */ + suspend fun send(params: ParamsOfSend) { + return tonClient.request("debot.send", params) + } + + /** + * Destroys debot handle. + * Removes handle from Client Context and drops debot engine referenced by that handle. + */ + suspend fun remove(params: ParamsOfRemove) { + return tonClient.request("debot.remove", params) + } + +} diff --git a/src/main/kotlin/ee/nx01/tonclient/debot/Types.kt b/src/main/kotlin/ee/nx01/tonclient/debot/Types.kt new file mode 100644 index 0000000..2b1113a --- /dev/null +++ b/src/main/kotlin/ee/nx01/tonclient/debot/Types.kt @@ -0,0 +1,133 @@ +package ee.nx01.tonclient.debot + +data class ParamsOfAppDebotBrowserLog( + val msg: String +) + +data class ParamsOfAppDebotBrowserSwitch( + val contextId: Long +) + +data class ParamsOfAppDebotBrowserShowAction( + val action: DebotAction +) + +data class ParamsOfAppDebotBrowserInput( + val prompt: String +) + +data class ResultOfAppDebotBrowserInput( + val value: String +) + +data class ResultOfAppDebotBrowserGetSigningBox( + val signingBox: Long +) + +data class ParamsOfAppDebotBrowserInvokeDebot( + val debotAddr: String, + val action: DebotAction +) + +data class ParamsOfAppDebotBrowserSend( + val message: String +) + +data class ParamsOfAppDebotBrowserApprove( + val activity: DebotActivity +) + +data class ResultOfAppDebotBrowserApprove( + val approved: Boolean +) + + +enum class AppDebotBrowserMessageType { + Log, Switch, SwitchCompleted, ShowAction, Input, GetSigningBox, InvokeDebot, Send, Approve +} + +data class ParamsOfAppDebotBrowser( + val type: AppDebotBrowserMessageType, + val msg: String? = null, + val contextId: Long? = null, + val action: DebotAction? = null, + val prompt: String? = null, + val debotAddr: String? = null, + val message: String? = null, + val activity: DebotActivity? = null +) + +data class DebotActivity( + val type: String = "Transaction", + val msg: String, + val dst: String, + val out: List = listOf(), + val fee: Long, + val setcode: Boolean, + val signkey: String, + val signing_box_handle: Long +) + +data class Spending( + val amount: Long, + val dst: String +) + +data class ParamsOfRemove( + val debotHandle: Long +) + +data class ParamsOfSend( + val debotHandle: Long, + val message: String +) + +data class ParamsOfExecute( + val debotHandle: Long, + val action: DebotAction +) + +data class DebotAction( + val description: String, + val name: String, + val actionType: Long, + val to: Long, + val attributes: String, + val misc: String +) + +data class ResultOfFetch( + val info: DebotInfo +) + +data class ParamsOfFetch( + val address: String +) + +data class ParamsOfStart( + val debotHandle: Long +) + +data class ParamsOfInit( + val address: String +) + +data class RegisteredDebot( + val debotHandle: Long, + val debotAbi: String, + val info: DebotInfo +) + +data class DebotInfo( + val name: String? = null, + val version: String? = null, + val publisher: String? = null, + val caption: String? = null, + val author: String? = null, + val support: String? = null, + val hello: String? = null, + val language: String? = null, + val dabi: String? = null, + val icon: String? = null, + val interfaces: List = listOf() +) diff --git a/src/main/resources/natives/linux_64/libtonclientjni.so b/src/main/resources/natives/linux_64/libtonclientjni.so index 0fc6969..192d81a 100644 Binary files a/src/main/resources/natives/linux_64/libtonclientjni.so and b/src/main/resources/natives/linux_64/libtonclientjni.so differ diff --git a/src/main/resources/natives/osx_64/libtonclientjni.dylib b/src/main/resources/natives/osx_64/libtonclientjni.dylib index 9943730..7d0e7cd 100644 Binary files a/src/main/resources/natives/osx_64/libtonclientjni.dylib and b/src/main/resources/natives/osx_64/libtonclientjni.dylib differ diff --git a/src/main/resources/natives/windows_64/tonclientjni.dll b/src/main/resources/natives/windows_64/tonclientjni.dll index c37d580..f35bfaa 100644 Binary files a/src/main/resources/natives/windows_64/tonclientjni.dll and b/src/main/resources/natives/windows_64/tonclientjni.dll differ diff --git a/src/test/kotlin/ee/nx01/tonclient/TestConstants.kt b/src/test/kotlin/ee/nx01/tonclient/TestConstants.kt index 78e6b03..fcff816 100644 --- a/src/test/kotlin/ee/nx01/tonclient/TestConstants.kt +++ b/src/test/kotlin/ee/nx01/tonclient/TestConstants.kt @@ -2,11 +2,11 @@ package ee.nx01.tonclient object TestConstants { val WALLET_PHRASE = "defense talent layer admit setup virus deer buffalo timber ethics symbol cover" - val WALLET_ADDRESS = "0:c1c52894eb07f12ba110ff4be2d115ab09d0b06ba44ff9d6d31459a00d4e58ef" - val MESSAGE_ID = "94a29f117ef5c1afbc0ee129e9a9c014aa9261ce285b1e7597d0282e0aa29cf5" - val BLOCK_ID = 171453f - val TRANSACTION_ID = "883f0058b814f2cf9ec8caeae02db34e505409247f5a5f002ed9063d3a5c56e8" - val KEY_BLOCK_ID = "8734c2bdfe82c1b5c5aa7c7b5267733e3b312c63224c0d2ad9b2f7f382ead012" + val WALLET_ADDRESS = "0:7f458ae01e28573a181e2227dc77710d6421d4e103fdd3e023200aa4bce83950" + val MESSAGE_ID = "8fad5a4e275f921ac19b22d00533c48cee277b93bea309317470340b64294baf" + val BLOCK_ID = 452651f + val TRANSACTION_ID = "4f5a7c06d287f0c41b3cb7795605a96491fb275ae2edf02612638c30ef430576" + val KEY_BLOCK_ID = "f2cfde69312a330f70f671f66ce13bdc5a514f30844c698643ac39aee4e2b890" val WALLET_SECRET = "db16e21ee91b5064f6e31d9a2fb4771ce7f8acf14fe6d6ffade8ffcbeec31d69" val WALLET_PUBLIC = "335c317bfef32545749a665bfec97f692fdc107d0867a1a1e1b2d2906b40d24c" diff --git a/src/test/kotlin/ee/nx01/tonclient/debot/DeBotModuleTest.kt b/src/test/kotlin/ee/nx01/tonclient/debot/DeBotModuleTest.kt new file mode 100644 index 0000000..2e437ff --- /dev/null +++ b/src/test/kotlin/ee/nx01/tonclient/debot/DeBotModuleTest.kt @@ -0,0 +1,32 @@ +package ee.nx01.tonclient.debot + +import ee.nx01.tonclient.NetworkConfig +import ee.nx01.tonclient.TonClient +import ee.nx01.tonclient.TonClientConfig +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.shouldNotBe + +class DeBotModuleTest : StringSpec({ + + "Should be able init and start deboot" { + val client = TonClient(TonClientConfig(network = NetworkConfig("main.ton.dev"))) + + val response = client.debot.init(ParamsOfInit("0:038081930f6b5211ba2c9e36cb28945954c35ccd913872a4b17b2671b83f2a88")) { + println(it) + } + + response shouldNotBe null + + client.debot.start(ParamsOfStart(response.debotHandle)) + + Thread.sleep(3000) + } + + "Should be able fetch" { + val client = TonClient(TonClientConfig(network = NetworkConfig("main.ton.dev"))) + + val response = client.debot.fetch(ParamsOfFetch("0:038081930f6b5211ba2c9e36cb28945954c35ccd913872a4b17b2671b83f2a88")) + + response shouldNotBe null + } +}) diff --git a/src/test/kotlin/ee/nx01/tonclient/net/NetModuletTest.kt b/src/test/kotlin/ee/nx01/tonclient/net/NetModuletTest.kt index 04e7eee..9f93e38 100644 --- a/src/test/kotlin/ee/nx01/tonclient/net/NetModuletTest.kt +++ b/src/test/kotlin/ee/nx01/tonclient/net/NetModuletTest.kt @@ -79,7 +79,7 @@ class NetModuletTest : StringSpec({ "Query transaction tree" { val client = TonClient() - val response = client.net.queryTransactionTree(ParamsOfQueryTransactionTree("94a29f117ef5c1afbc0ee129e9a9c014aa9261ce285b1e7597d0282e0aa29cf5")) + val response = client.net.queryTransactionTree(ParamsOfQueryTransactionTree(TestConstants.MESSAGE_ID)) response.messages shouldNotBe null