Snippets

chromawallet ExternalCall

Created by Alex Mizrahi
package net.postchain.somethign

import net.postchain.base.SpecialTransactionPosition
import net.postchain.common.BlockchainRid
import net.postchain.core.BlockEContext
import net.postchain.crypto.CryptoSystem
import net.postchain.gtv.GtvDictionary
import net.postchain.gtv.GtvFactory.gtv
import net.postchain.gtv.GtvNull
import net.postchain.gtx.GTXModule
import net.postchain.gtx.GTXSpecialTxExtension
import net.postchain.gtx.OpData
import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.task
import org.web3j.abi.datatypes.Bool
import java.lang.Exception
import java.lang.Thread.sleep

class ExternalAuth: GTXSpecialTxExtension {
    override fun getRelevantOps(): Set<String> {
        return setOf("__auth")
    }

    lateinit var module: GTXModule

    data class Response(var resolved: Boolean, var authorized: Boolean
        var task: Promise<Unit, Exception>?
    )

    val pendingRequests = mutableMapOf<String, Response>()

    override fun init(module: GTXModule, blockchainRID: BlockchainRid, cs: CryptoSystem) {
        this.module = module
    }

    override fun needsSpecialTransaction(position: SpecialTransactionPosition): Boolean {
        return position == SpecialTransactionPosition.Begin
    }

    fun callExternalService(id: String): Boolean {
        sleep(1000)
        return true
    }

    override fun createSpecialOperations(position: SpecialTransactionPosition, bctx: BlockEContext): List<OpData> {
        if (position == SpecialTransactionPosition.Begin) {
            val retval = mutableListOf<OpData>()
            val rqs = this.module.query(bctx, "get_auth_requests",
                    GtvDictionary.build(mapOf()))

            for (r in rqs.asArray()) {
                val rString = r.asString()
                val res = pendingRequests[rString]
                if (res != null) {
                    if (res.resolved) {
                        retval.add(OpData("__auth",
                           arrayOf(
                                   r,
                                   gtv(if (res.authorized) 1 else 0)

                           )))
                    } else {
                        // otherwise we are waiting till it resolves
                    }
                } else {
                    val res = Response(false, false, null)
                    pendingRequests[rString] = res
                    res.task = task {
                        val externalResponse = callExternalService(rString)
                        res.resolved = true
                        res.authorized = externalResponse
                    }
                }
            }
            return retval
        } else return listOf()
    }

    override fun validateSpecialOperations(position: SpecialTransactionPosition, bctx: BlockEContext, ops: List<OpData>): Boolean {
        if (position == SpecialTransactionPosition.Begin) {
            for (op in ops) {
                if (op.opName != "__auth") return false
                val rString = op.args[0].toString()
                val authorized = op.args[1].asInteger() == 1L
                val res = pendingRequests[rString]
                if (res != null) {
                    if (!res.resolved) res.task!!.get()
                    if (!res.resolved) return false // ok it probably crashed, do something reasonable?
                    if (res.authorized != authorized) return false
                } else {
                    val ext_authorized = callExternalService(rString)
                    if (authorized != ext_authorized) return false
                }
            }
        }
        return true
    }
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.