diff --git a/build.gradle.kts b/build.gradle.kts index 7618f7cb..c459dd42 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -72,6 +72,9 @@ dependencies { // unique implementation ("network.unique:unique-sdk-jvm:0.0.1") + // algorand + implementation ("com.algorand:algosdk:2.2.0") + // expediagroup graphql implementation("com.expediagroup:graphql-kotlin-spring-client:6.4.0") implementation("com.expediagroup", "graphql-kotlin-client-serialization", "6.4.0") diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a5bd6b32..f72df95a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists \ No newline at end of file +zipStorePath=wrapper/dists diff --git a/js/app.ts b/js/app.ts index d3715fc8..e2d8652d 100644 --- a/js/app.ts +++ b/js/app.ts @@ -10,12 +10,11 @@ import {NearRoutes} from './near/near.routes.config'; import {FlowRoutes} from './Flow/flow.routes.config'; import {PolkadotRoutes} from './polkadot/polkadot.routes.config'; - import debug from 'debug'; const app: express.Application = express(); const server: http.Server = http.createServer(app); -const port = 3000; +const port = 4000; const routes: Array = []; const debugLog: debug.IDebugger = debug('app'); @@ -57,4 +56,4 @@ server.listen(port, () => { routes.forEach((route: CommonRoutesConfig) => { debugLog(`Routes configured for ${route.getName()}`); }); -}); \ No newline at end of file +}); diff --git a/js/package-lock.json b/js/package-lock.json index 83daa8c7..fbcd6e87 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -25,6 +25,7 @@ "winston": "^3.8.2" }, "devDependencies": { + "@types/bn.js": "^5.1.1", "@types/cors": "^2.8.12", "@types/debug": "^4.1.7", "@types/express": "^4.17.14", @@ -1181,7 +1182,7 @@ }, "node_modules/@types/bn.js": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", + "resolved": "https://registry.npmmirror.com/@types/bn.js/-/bn.js-5.1.1.tgz", "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", "dependencies": { "@types/node": "*" diff --git a/js/package.json b/js/package.json index b7178f00..22645caa 100644 --- a/js/package.json +++ b/js/package.json @@ -28,6 +28,7 @@ "winston": "^3.8.2" }, "devDependencies": { + "@types/bn.js": "^5.1.1", "@types/cors": "^2.8.12", "@types/debug": "^4.1.7", "@types/express": "^4.17.14", diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..3e16bdf2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "waltid-nftkit", + "lockfileVersion": 2, + "requires": true, + "packages": {} +} diff --git a/src/main/kotlin/id/walt/nftkit/App.kt b/src/main/kotlin/id/walt/nftkit/App.kt index 66065783..4ffed1b8 100644 --- a/src/main/kotlin/id/walt/nftkit/App.kt +++ b/src/main/kotlin/id/walt/nftkit/App.kt @@ -1,14 +1,15 @@ package id.walt.nftkit + import id.walt.nftkit.rest.NftKitApi fun main() { println("\n\n\n") - /* /////////// */ /* /////////// */ /* /////////// */ + NftKitApi.start() diff --git a/src/main/kotlin/id/walt/nftkit/Values.kt b/src/main/kotlin/id/walt/nftkit/Values.kt index 64ecdb14..f541d1b8 100644 --- a/src/main/kotlin/id/walt/nftkit/Values.kt +++ b/src/main/kotlin/id/walt/nftkit/Values.kt @@ -40,4 +40,17 @@ object Values { const val POLKADOT_UNIQUE_EXPLORER = "https://unique.subscan.io/" const val POLKADOT_OPAL_EXPLORER = "https://uniquescan.io/OPAL/" + + //algorand values + const val ALGORAND_INDEXER_TESTNET= "https://testnet-algorand.api.purestake.io/idx2"; + const val ALGORAND_INDEXER_MAINNET= "https://mainnet-algorand.api.purestake.io/idx2"; + + const val ALGORAND_ALGOD_TESTNET = "https://testnet-algorand.api.purestake.io/ps2"; + const val ALGORAND_ALGOD_MAINNET = "https://mainnet-algorand.api.purestake.io/ps2"; + + + + const val ALGORAND_MAINNET_EXPLORER = "https://algoexplorer.io/" + const val ALGORAND_TESTNET_EXPLORER = "https://testnet.algoexplorer.io/" + } diff --git a/src/main/kotlin/id/walt/nftkit/rest/AlgorandNftController.kt b/src/main/kotlin/id/walt/nftkit/rest/AlgorandNftController.kt new file mode 100644 index 00000000..fefcca36 --- /dev/null +++ b/src/main/kotlin/id/walt/nftkit/rest/AlgorandNftController.kt @@ -0,0 +1,125 @@ +package id.walt.nftkit.rest + +import cc.vileda.openapi.dsl.schema + +import id.walt.nftkit.services.* +import id.walt.nftkit.tokenownersquery.TokenOwnersDataResponse +import id.walt.nftkit.utilis.Common +import io.javalin.http.Context +import io.javalin.plugin.openapi.dsl.document +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json + + + +object AlgorandNftController{ + + private const val TAG = "Algorand Blockchain: Non-fungible tokens(NFTs)" + fun accountCreation(ctx : Context){ + val result = AlgorandNftService.createAccount() + ctx.json(result) + } + + fun accountCreationDocs() = document().operation { + it.summary("Create Algorand Account").operationId("CreateAlgorandAccount").addTagsItem("Algorand Blockchain: Non-fungible tokens(NFTs)") + }.json(200.toString()) { + it.description("Algorand Account") + } + + + fun assetCreation(ctx : Context){ + val result = AlgorandNftService.createAssetArc3(ctx.pathParam("assetName"), ctx.pathParam("assetUnitName"), ctx.pathParam("url")) + ctx.json(result) + } + + fun assetCreationDocs() = document().operation { + it.summary("Create Algorand Asset").operationId("CreateAlgorandAsset").addTagsItem("Algorand Blockchain: Non-fungible tokens(NFTs)") + }.json(200.toString()) { + it.description("Algorand Asset") + } + + + + + + fun fetchToken(ctx: Context){ + val chain =ctx.pathParam("chain") + val asset = ctx.pathParam("assetId") + val response = AlgorandNftService.getToken( + asset.toLong(), + Common.getAlgorandChain(chain.uppercase()) + ) + ctx.json(response) + } + fun fetchTokenDocs()= document().operation { + it.summary("Fetching Token") + .operationId("fetchToken") + .addTagsItem(TAG)} + .pathParam("chain") { + it.schema{}} + .pathParam("assetId"){} + .json("200"){ + it.description("Fetched token") + } + + /////////////////////////////////////////////////////////////////////////// + + fun fetchAssetMetadata(ctx: Context){ + val chain =ctx.pathParam("chain") + val asset = ctx.pathParam("assetId") + val response = AlgorandNftService.getAssetMeatadata( + asset.toLong(), + Common.getAlgorandChain(chain.uppercase()) + ) + ctx.json(response) + } + fun fetchAssetMetadataDocs()= document().operation { + it.summary("Fetching token parametrs ") + .operationId("fetchAlgornadAssets") + .addTagsItem(TAG)} + .pathParam("chain") { + it.schema{}} + .pathParam("assetId"){} + .json("200"){ + it.description("Fetched token parameteres") + } + + /////////////////////////////////////////////////////////////////////////// + + fun fetchAccountAssets(ctx: Context){ + val chain = ctx.pathParam("chain") + val address = ctx.pathParam("address") + val response = AlgorandNftService.getAccountAssets(address, Common.getAlgorandChain(chain.uppercase())) + ctx.json(response) + } + fun fetchAccountAssetsDocs()= document().operation { + it.summary("Fetching account tokens ") + .operationId("fetchAccountAssets") + .addTagsItem(TAG)} + .pathParam("chain") { + it.schema{}} + .pathParam("address"){} + .json("200"){ + it.description("Fetched Tokens") + } + + /////////////////////////////////////////////////////////////////////////// + + fun fetchNftMetadata(ctx: Context){ + val chain =ctx.pathParam("chain") + val asset = ctx.pathParam("assetId") + val result = AlgorandNftService.getNftMetadata(asset.toLong(), Common.getAlgorandChain(chain.uppercase()) ) + ctx.result(Json.encodeToString(result)) + + } + fun fetchNftMetadataDocs()= document().operation { + it.summary("Fetching NFT metadata ") + .operationId("fetchAlgornadNfts") + .addTagsItem(TAG)} + .pathParam("chain") { + it.schema{}} + .pathParam("assetId"){} + .json("200"){ + it.description("Fetched NFT metadata") + } +} \ No newline at end of file diff --git a/src/main/kotlin/id/walt/nftkit/rest/NftKitApi.kt b/src/main/kotlin/id/walt/nftkit/rest/NftKitApi.kt index e8c3e095..54a40ef2 100644 --- a/src/main/kotlin/id/walt/nftkit/rest/NftKitApi.kt +++ b/src/main/kotlin/id/walt/nftkit/rest/NftKitApi.kt @@ -279,6 +279,34 @@ object NftKitApi { ) } + + path("Algorand"){ + + post("account/create/", + documented(AlgorandNftController.accountCreationDocs(), AlgorandNftController::accountCreation) + ) + post("asset/create/{assetName}/{assetUnitName}/{url}/", + documented(AlgorandNftController.assetCreationDocs(), AlgorandNftController::assetCreation) + ) + + get( + "chain/{chain}/asset/{assetId}", + documented(AlgorandNftController.fetchTokenDocs(), AlgorandNftController::fetchToken) + ) + get( + "chain/{chain}/asset/{assetId}/params", + documented(AlgorandNftController.fetchAssetMetadataDocs(), AlgorandNftController::fetchAssetMetadata) + ) + get( + "chain/{chain}/asset/{assetId}/metadata", + documented(AlgorandNftController.fetchNftMetadataDocs(), AlgorandNftController::fetchNftMetadata) + ) + get( + "chain/{chain}/assets/account/{address}/", + documented(AlgorandNftController.fetchAccountAssetsDocs(), AlgorandNftController::fetchAccountAssets) + ) + + } } path("nft/verifier") { get( diff --git a/src/main/kotlin/id/walt/nftkit/rest/TezosNftController.kt b/src/main/kotlin/id/walt/nftkit/rest/TezosNftController.kt index d69fca53..9ab3e904 100644 --- a/src/main/kotlin/id/walt/nftkit/rest/TezosNftController.kt +++ b/src/main/kotlin/id/walt/nftkit/rest/TezosNftController.kt @@ -101,8 +101,7 @@ object TezosNftController { val chain = ctx.pathParam("chain") val contractAddress = ctx.pathParam("contractAddress") val tokenId = ctx.pathParam("tokenId") - val result = - TezosNftService.getNftTezosMetadata(Common.getTezosChain(chain.uppercase()), contractAddress, tokenId) + val result = TezosNftService.getNftTezosMetadata(Common.getTezosChain(chain.uppercase()), contractAddress, tokenId) result?.let { ctx.json( it @@ -140,4 +139,4 @@ object TezosNftController { } -} \ No newline at end of file +} diff --git a/src/main/kotlin/id/walt/nftkit/services/AlgorandNftService.kt b/src/main/kotlin/id/walt/nftkit/services/AlgorandNftService.kt new file mode 100644 index 00000000..53ae11ff --- /dev/null +++ b/src/main/kotlin/id/walt/nftkit/services/AlgorandNftService.kt @@ -0,0 +1,261 @@ +package id.walt.nftkit.services + +import com.algorand.algosdk.account.Account +import com.algorand.algosdk.crypto.Address +import com.algorand.algosdk.transaction.Transaction +import com.algorand.algosdk.util.Encoder +import com.algorand.algosdk.v2.client.common.AlgodClient +import com.algorand.algosdk.v2.client.common.IndexerClient + +import id.walt.nftkit.Values.ALGORAND_TESTNET_EXPLORER +import id.walt.nftkit.metadata.IPFSMetadata +import id.walt.nftkit.services.WaltIdServices.loadAlgorand +import io.ktor.client.* +import io.ktor.client.call.* +import io.ktor.client.engine.cio.* +import io.ktor.client.plugins.contentnegotiation.* +import io.ktor.client.plugins.logging.* +import io.ktor.client.request.* +import io.ktor.http.* +import io.ktor.serialization.kotlinx.json.* +import kotlinx.coroutines.runBlocking +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonElement + + +enum class AlgorandChain { + TESTNET, + MAINNET, + BETANET +} + +@Serializable +data class AlgorandAccount(val address: String, val mnemonic: String) + +@Serializable +data class AlgodResponse(val txId: String , val explorerUrl: String) + +@Serializable +data class AlgorandToken + ( + var TokenParams: Asset?= null, + var Metadata : AlgoNftMetadata? = null +) + +@Serializable +data class Asset ( + var index: Long? = null, + @SerialName("created-at-round") + var createdAtRound: Long? = null, + var deleted: Boolean? = null, + @SerialName("destroyed-at-round") + var destroyedAtRound: Long? = null, + @SerialName("params") + var params: AssetParams? = null +){ + @Serializable + data class AssetParams( + var clawback: String? = null, + var creator: String? = null, + var decimals: Long? = null, + @SerialName("default-frozen") + var defaultFrozen: Boolean? = null, + var freeze: String? = null, + var manager: String? = null, + var name: String? = null, + var reserve: String? = null, + var total: Long? = null, + @SerialName("unit-name") + var unitName: String? = null, + var url: String? = null + ) +} + + +@Serializable +data class AssetHoldingsResponse ( + var assets: List = ArrayList()) +{ + @Serializable + data class AssetHolding( + var amount: Int? = null, + @SerialName("asset-id") + var assetId: Long? = null, + @SerialName("deleted") + var deleted: Boolean? = null, + @SerialName("is-frozen") + var isFrozen: Boolean? = null, + ) +} + + +@Serializable +data class AlgoNftMetadata ( + var name: String? = null, + var description: String? = null, + var image: String? = null, + var decimals: Int? = null, + var unitName: String? = null, + //var properties : Map ? = null, +) + +object AlgorandNftService { + + val client1 = HttpClient(CIO.create { requestTimeout = 0 }) { + install(ContentNegotiation) { + json(Json { + ignoreUnknownKeys = true + }) + } + install(Logging) { +// logger = Logger.SIMPLE +// level = LogLevel.ALL + level = LogLevel.BODY + } + expectSuccess = false + } + + val ALGOD_API_ADDR = "https://testnet-algorand.api.purestake.io/ps2" + val IDX_API_ADDR = "https://testnet-algorand.api.purestake.io/idx2" + + val ALGOD_PORT = 443 + val ALGOD_API_TOKEN_KEY = "X-API-Key" + val ALGOD_API_TOKEN = "B3SU4KcVKi94Jap2VXkK83xx38bsv95K5UZm2lab" + val client = AlgodClient(ALGOD_API_ADDR, ALGOD_PORT, ALGOD_API_TOKEN, ALGOD_API_TOKEN_KEY) + val idxClient = IndexerClient(IDX_API_ADDR, ALGOD_PORT, ALGOD_API_TOKEN, ALGOD_API_TOKEN_KEY) + fun createAccount(): AlgorandAccount { + val account = com.algorand.algosdk.account.Account() + return AlgorandAccount(account.address.toString(), account.toMnemonic()) + } + + + fun createAssetArc3(assetName : String , assetUnitName : String , url : String) : AlgodResponse{ + + val SRC_ACCOUNT = loadAlgorand().algorandConfig.algorand_seed_Mnemonic + val src = Account(SRC_ACCOUNT) + println(src.getAddress()) + + val params = client.TransactionParams().execute().body() + + val tx = Transaction.AssetCreateTransactionBuilder() + .suggestedParams(params) + .sender(src.address) + .manager(src.address) + .reserve(src.address) + .freeze(src.address) + .clawback(src.address) + .assetTotal(1) + .assetDecimals(0) + .defaultFrozen(false) + .assetUnitName(assetUnitName) + .assetName(assetName) + .url("$url#arc3") + .build() + val signedTx = src.signTransaction(tx) + + // send the transaction to the network + try { + val txHeaders = arrayOf("Content-Type") + val txValues = arrayOf("application/x-binary") + val encodedTxBytes = Encoder.encodeToMsgPack(signedTx) + + val txResponse = client.RawTransaction().rawtxn(encodedTxBytes).execute(txHeaders, txValues).body() + println("Successfully sent tx with ID " + txResponse.txId) + return AlgodResponse(txResponse.txId , "$ALGORAND_TESTNET_EXPLORER"+"tx/${txResponse.txId}") + } catch (e: Exception) { + e.printStackTrace() + } + return AlgodResponse("Null" , "Null") + } + +// fun getAssetMeatadata(assetId: Long, chain: AlgorandChain) : Asset { +// +// val ALGOD_API_ADDR = when (chain) { +// AlgorandChain.MAINNET -> "https://mainnet-api.algonode.cloud" +// AlgorandChain.TESTNET -> "https://testnet-api.algonode.cloud" +// AlgorandChain.BETANET -> "https://betanet-api.algonode.cloud" +// } +// var client = AlgodClient(ALGOD_API_ADDR, ALGOD_PORT, ALGOD_API_TOKEN) +// +// return client.GetAssetByID(assetId).execute().body() +// +// } +// fun getNftMetadata(assetId: Long, chain: AlgorandChain):AlgoNftMetadata{ +// +// return runBlocking { +// +// val asset: Asset = getAssetMeatadata(assetId, chain) +// var cid = (asset.params.url).substringAfter("ipfs://") +// val nft = IPFSMetadata.client.get("https://ipfs.algonode.xyz/ipfs/$cid") {}.body() +// +// return@runBlocking nft; +// } +// } + + fun getToken(assetId: Long, chain: AlgorandChain): AlgorandToken { + return runBlocking { + val ALGOD_API_ADDR = when (chain) { + AlgorandChain.MAINNET -> "https://mainnet-api.algonode.cloud" + AlgorandChain.TESTNET -> "https://testnet-api.algonode.cloud" + AlgorandChain.BETANET -> "https://betanet-api.algonode.cloud" + } + val tokenParams = client1.get(ALGOD_API_ADDR + "/v2/assets/" + assetId){ + contentType(ContentType.Application.Json) + }.body() + + var cid = (tokenParams.params?.url)?.substringAfter("ipfs://") + val nft = + IPFSMetadata.client.get("https://ipfs.io/ipfs/$cid") + { contentType(ContentType.Application.Json)}.body() + + var result = AlgorandToken() + + result.TokenParams = tokenParams + result.Metadata = nft + return@runBlocking result + } + } + fun getAssetMeatadata(assetId: Long, chain: AlgorandChain): Asset { + return runBlocking { + val ALGOD_API_ADDR = when (chain) { + AlgorandChain.MAINNET -> "https://mainnet-api.algonode.cloud" + AlgorandChain.TESTNET -> "https://testnet-api.algonode.cloud" + AlgorandChain.BETANET -> "https://betanet-api.algonode.cloud" + } + val asset = client1.get(ALGOD_API_ADDR + "/v2/assets/" + assetId){ + contentType(ContentType.Application.Json) + }.body() + + return@runBlocking asset + } + } + + fun getNftMetadata(assetId: Long, chain: AlgorandChain): AlgoNftMetadata { + return runBlocking { + val asset: Asset = getAssetMeatadata(assetId, chain) + var cid = (asset.params?.url)?.substringAfter("ipfs://") + val nft = + IPFSMetadata.client.get("https://ipfs.algonode.xyz/ipfs/$cid") + { contentType(ContentType.Application.Json)}.body() + return@runBlocking nft; + } + } + + fun getAccountAssets(address: String, chain: AlgorandChain): AssetHoldingsResponse { + return runBlocking { + var ALGOD_API_ADDR = when (chain) { + AlgorandChain.MAINNET -> "https://mainnet-idx.algonode.cloud" + AlgorandChain.TESTNET -> "https://testnet-idx.algonode.cloud" + AlgorandChain.BETANET -> "https://betanet-idx.algonode.cloud" + } + val add = Address(address); + val result = + client1.get(ALGOD_API_ADDR + "/v2/accounts/" + add + "/assets") { + contentType(ContentType.Application.Json) + }.body() + return@runBlocking result; + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/id/walt/nftkit/services/JsonConverter.kt b/src/main/kotlin/id/walt/nftkit/services/JsonConverter.kt new file mode 100644 index 00000000..3a417d9d --- /dev/null +++ b/src/main/kotlin/id/walt/nftkit/services/JsonConverter.kt @@ -0,0 +1,40 @@ +package id.walt.nftkit.services + +import kotlinx.serialization.json.* +import kotlin.reflect.jvm.jvmName + +object JsonConverter { + + fun toJsonElement(value: Any?): JsonElement { + return when (value) { + is Number -> JsonPrimitive(value) + is String -> JsonPrimitive(value) + is Boolean -> JsonPrimitive(value) + null -> JsonNull + + is List<*> -> buildJsonArray { value.forEach { add(toJsonElement(it)) } } + is Map<*, *> -> buildJsonObject { value.keys.forEach { put(it.toString(), toJsonElement(value[it])) } } + + is JsonElement -> value + + //else -> JsonNull + else -> throw IllegalArgumentException("Json values can only be Number, String, Boolean, Null, List or Map, not \"${value::class.jvmName}\": toString = $value") + } + } + + fun fromJsonElement(element: JsonElement): Any? { + return when (element) { + is JsonPrimitive -> when { + element.isString -> element.contentOrNull + else -> element.booleanOrNull ?: element.longOrNull ?: element.doubleOrNull + } + + is JsonArray -> element.map { fromJsonElement(it) }.toList() + is JsonObject -> element.keys.associateWith { + fromJsonElement(element[it] ?: JsonNull) + } + else -> throw IllegalArgumentException("Invalid JSON element \"${element::class.jvmName}\": $element") + } + } + +} diff --git a/src/main/kotlin/id/walt/nftkit/services/WaltIdServices.kt b/src/main/kotlin/id/walt/nftkit/services/WaltIdServices.kt index a178eaac..29619aa2 100644 --- a/src/main/kotlin/id/walt/nftkit/services/WaltIdServices.kt +++ b/src/main/kotlin/id/walt/nftkit/services/WaltIdServices.kt @@ -24,6 +24,9 @@ data class PolkadotConfig(val polkadotAccounts: Map) data class IndexersUrl(val uniqueUrl: String, val opalUrl: String) data class Indexers(val indexersUrl : IndexersUrl) +data class algorandSeedMnemonic(val algorand_seed_Mnemonic : String) +data class Algorand(val algorandConfig : algorandSeedMnemonic) + @@ -85,6 +88,15 @@ object WaltIdServices { .loadConfigOrThrow() + fun loadAlgorand() = ConfigLoader.builder() + .addFileExtensionMapping("yaml", YamlParser()) + .addSource(PropertySource.file(File("$WALTID_CONFIG_PATH/walt.yaml"), optional = true)) + .addSource(PropertySource.resource(default_yaml_path)) + .build() + .loadConfigOrThrow() + + + fun getBlockExplorerUrl(chain: EVMChain): String { return when (chain) { EVMChain.ETHEREUM -> Values.ETHEREUM_MAINNET_BLOCK_EXPLORER_URL diff --git a/src/main/kotlin/id/walt/nftkit/utilis/Common.kt b/src/main/kotlin/id/walt/nftkit/utilis/Common.kt index fe1c5e1b..5c1e9296 100644 --- a/src/main/kotlin/id/walt/nftkit/utilis/Common.kt +++ b/src/main/kotlin/id/walt/nftkit/utilis/Common.kt @@ -65,6 +65,14 @@ object Common { } } + fun getAlgorandChain(chain: String): AlgorandChain{ + return chain.let { + if (it.isEmpty()){ + throw Exception("No chain defined") + } + AlgorandChain.valueOf(it.uppercase()) + } + } fun getFa2SmartContractType(type: String): Fa2SmartContractType{ return type.let { if (it.isEmpty()){ @@ -133,5 +141,11 @@ object Common { if(chain in uniqueParachain) return true return false } + + fun isAlgorandChain(chain: Chain): Boolean{ + val algorandChains= listOf(Chain.MAINNET, Chain.TESTNET) + if(chain in algorandChains) return true + return false + } } diff --git a/src/main/resources/walt-default.yaml b/src/main/resources/walt-default.yaml index 73a620fc..6537954d 100644 --- a/src/main/resources/walt-default.yaml +++ b/src/main/resources/walt-default.yaml @@ -57,9 +57,14 @@ apiKeys: ethereumBlockExplorer: "JGD5ZUUBHE8CUXPNKZASVQPHRGBMB7A5XV" polygonBlockExplorer: "DZ3PFVWGJE5B8DMDQPRZ5JFBR6U484B82G" alchemy: "5TYSteGJgJwJjaQTNN3j_4JtYcvdr3Uy" - nftstorage: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDYwNDNEYThENjU2RTU3NTg2ZDk3MkM1ZDM5RUNENzI1NTNCM2Q1NjAiLCJpc3MiOiJuZnQtc3RvcmFnZSIsImlhdCI6MTY1NDYxNTQ2NjIwNCwibmFtZSI6Ik5GVCBLSVQifQ.PkMJpU3aJMQXqzq1nPnHJcWJR-32as3bQed3GBszMdg" + nftstorage: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweEIwNGU5YzMyNzczNjI1MEQ0QTkzQjZmYThjODUwNzQwQkI0N0YyMmYiLCJpc3MiOiJuZnQtc3RvcmFnZSIsImlhdCI6MTY2ODU1MDg4NjY2MywibmFtZSI6Ik5GVF9URVNUIn0._DnFeEpPXVF4KqIoRRRV2O67HgjGSyYJgpXFhhf-FD4" subscan: "" + + +algorandConfig: + algorand_seed_Mnemonic: "famous hood lend donate orange globe spatial stamp opinion universe found gown river identify negative climb defy galaxy turkey height duty doctor hazard ability athlete" + #for local dev use: tezosBackendServer: "http://localhost:3000" tezosBackendServer: "http://nftkit-js:80"