From 2e25e51b508c70cfb465aa1be5eb49e3066a83df Mon Sep 17 00:00:00 2001 From: Sergey Bushnyak Date: Sun, 19 Nov 2023 19:21:25 +0200 Subject: [PATCH] update deps --- lib/src/acme_client.dart | 4 +- lib/src/v3/acme_client.dart | 785 ++++++++++++++++++++++++++++++++++++ lib/src/v3/enums.dart | 6 + pubspec.yaml | 10 +- 4 files changed, 798 insertions(+), 7 deletions(-) create mode 100644 lib/src/v3/acme_client.dart create mode 100644 lib/src/v3/enums.dart diff --git a/lib/src/acme_client.dart b/lib/src/acme_client.dart index b23c230..d243b0f 100644 --- a/lib/src/acme_client.dart +++ b/lib/src/acme_client.dart @@ -154,14 +154,14 @@ class ACMEClient { } Future> queryMinorBlocks( - String url, QueryPaginationForBlocks pagination, MinorBlocksQueryOptions? options) { + String url, QueryPaginationForBlocks pagination, MinorBlocksQueryOptions? options, [bool? supressLog]) { Map params = {}; params.addAll({"url": url}); params.addAll(pagination.toMap); if (options != null) { params.addAll(options.toMap); } - return call("query-minor-blocks", params); + return call("query-minor-blocks", params, supressLog); } Future> queryMajorBlocks( diff --git a/lib/src/v3/acme_client.dart b/lib/src/v3/acme_client.dart new file mode 100644 index 0000000..f80416b --- /dev/null +++ b/lib/src/v3/acme_client.dart @@ -0,0 +1,785 @@ +import "dart:async"; +import 'dart:collection'; +import 'dart:developer'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:accumulate_api/accumulate_api.dart'; +import 'package:hex/hex.dart'; +import 'package:accumulate_api/src/model/query_transaction_response_model.dart' as query_trx_res_model; +import 'package:accumulate_api/src/model/tx.dart' as txModel; + +class ACMEClientV3 { + late RpcClient _rpcClient; + + ACMEClientV3(String endpoint) { + _rpcClient = RpcClient(endpoint); + } + + Future> call(String method, [Map? params, bool? supressLog]) { + return _rpcClient.call(method, params, supressLog); + } + + Future> _execute(AccURL principal, Payload payload, TxSigner signer) async { + HeaderOptions? options; + if (payload.memo != null) { + options = HeaderOptions(); + options.memo = payload.memo; + } + + if (payload.metadata != null) { + if (options == null) { + options = HeaderOptions(); + } + options.metadata = payload.metadata; + } + + final header = Header(principal, options); + final tx = Transaction(payload, header); + await tx.sign(signer); + + return execute(tx); + } + + Future> execute(Transaction tx) { + return call("execute", tx.toTxRequest().toMap); + } + + Future> executeDirect() { + return call( + "execute-direct", + ); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////// + + Future> queryAcmeOracle() { + return call("describe"); + } + + Future> queryData(dynamic url, [String? entryHash]) { + Map params = {}; + params.addAll({"url": url.toString()}); + if (entryHash != null && entryHash.isNotEmpty) { + params.addAll({"entryHash": entryHash}); + } + return call("query-data", params); + } + + Future> queryAnchor(String anchor) { + return this.queryUrl(ANCHORS_URL.toString() + ('/#anchor/$anchor')); + } + + Future> queryUrl(dynamic url, [QueryOptions? options]) { + Map params = {}; + params.addAll({"url": url.toString()}); + if (options != null) { + params.addAll(options.toMap); + } + + return call("query", params); + } + + Future> queryTx(String txRef, [TxQueryOptions? options]) { + String paramName = txRef.startsWith("acc://") ? "txIdUrl" : "txid"; + paramName = "txid"; + var txId = ""; + Map params = {}; + if (txRef.startsWith("acc://")) { + txId = txRef.substring(6).split("@")[0]; + } + params.addAll({paramName: txId}); + if (options != null) { + params.addAll(options.toMap); + } + + return call("query-tx", params); + } + + Future> queryTxByUrl(String txId, [TxQueryOptions? options]) { + String paramName = "txIdUrl"; + Map params = {}; + params.addAll({paramName: txId}); + if (options != null) { + params.addAll(options.toMap); + } + + return call("query-tx", params); + } + + Future> queryTxHistory(dynamic url, QueryPagination pagination, TxHistoryQueryOptions? options) { + Map params = {}; + params.addAll({"url": url.toString()}); + params.addAll(pagination.toMap); + if (options != null) { + params.addAll(options.toMap); + } + return call("query-tx-history", params, true); + } + + Future> queryDataSet(dynamic url, QueryPagination pagination, QueryOptions? options) { + Map params = {}; + params.addAll({"url": url.toString()}); + params.addAll(pagination.toMap); + if (options != null) { + params.addAll(options.toMap); + } + + return call("query-data-set", params); + } + + Future> queryKeyPageIndex(dynamic url, dynamic key) { + Map params = {}; + params.addAll({"url": url.toString()}); + params.addAll({"key": key is String ? key : HEX.encode(key)}); + + return call("query-key-index", params); + } + + Future> queryMinorBlocks( + String url, QueryPaginationForBlocks pagination, MinorBlocksQueryOptions? options) { + Map params = {}; + params.addAll({"url": url}); + params.addAll(pagination.toMap); + if (options != null) { + params.addAll(options.toMap); + } + return call("query-minor-blocks", params); + } + + Future> queryMajorBlocks( + String url, QueryPaginationForBlocks pagination, MinorBlocksQueryOptions? options) { + Map params = {}; + params.addAll({"url": url}); + params.addAll(pagination.toMap); + if (options != null) { + params.addAll(options.toMap); + } + return call("query-major-blocks", params); + } + + Future querySignerVersion(dynamic signer, Uint8List? publicKeyHash) async { + AccURL signerUrl; + Uint8List pkh; + if (signer is AccURL) { + signerUrl = signer; + if (publicKeyHash == null || publicKeyHash.isEmpty) { + throw Exception("Missing public key hash"); + } + pkh = publicKeyHash; + } else { + signerUrl = signer.url; + pkh = signer.publicKeyHash; + } + + Map res = await queryKeyPageIndex(signerUrl, pkh); + res = await queryUrl(res["result"]["data"]["keyPage"]); + return res["result"]["data"]["version"]; + } + + Future> queryDirectory(dynamic url, QueryPagination pagination, QueryOptions? options) { + Map params = {}; + params.addAll({"url": url.toString()}); + params.addAll(pagination.toMap); + if (options != null) { + params.addAll(options.toMap); + } + + return call("query-directory", params); + } + + waitOnTx(int startTime, String txId, [WaitTxOptions? options]) async { + Completer completer = Completer(); + + int timeout = options?.timeout ?? 30000; + final pollInterval = options?.pollInterval ?? 1000; + final ignoreSyntheticTxs = options?.ignoreSyntheticTxs ?? false; + + try { + final resp = await queryTx(txId); + query_trx_res_model.QueryTransactionResponseModel queryTransactionResponseModel = + query_trx_res_model.QueryTransactionResponseModel.fromJson(resp); + + if (queryTransactionResponseModel.result != null) { + query_trx_res_model.QueryTransactionResponseModelResult result = queryTransactionResponseModel.result!; + if (result.status != null) { + if (result.status!.delivered!) { + if (result.status!.failed != null) { + if (result.status!.failed!) { + print("${result.status?.toJson()}"); + completer.complete(false); + } + } + + log("${result.status!.delivered!} ${result.syntheticTxids}"); + if (ignoreSyntheticTxs) { + completer.complete(true); + } else { + if (result.syntheticTxids!.isNotEmpty) { + int nowTime = DateTime.now().millisecondsSinceEpoch; + if (nowTime - startTime < timeout) { + sleep(Duration(milliseconds: pollInterval)); + completer.complete(await waitOnTx(startTime, result.syntheticTxids!.first)); + } else { + completer.complete(false); + } + } else { + completer.complete(true); + } + } + } else { + int nowTime = DateTime.now().millisecondsSinceEpoch; + if (nowTime - startTime < timeout) { + sleep(Duration(milliseconds: pollInterval)); + completer.complete(await waitOnTx(startTime, txId)); + } else { + completer.complete(false); + } + } + } else { + int nowTime = DateTime.now().millisecondsSinceEpoch; + if (nowTime - startTime < timeout) { + sleep(Duration(milliseconds: pollInterval)); + completer.complete(await waitOnTx(startTime, txId)); + } else { + completer.complete(false); + } + } + } else { + int nowTime = DateTime.now().millisecondsSinceEpoch; + if (nowTime - startTime < timeout) { + sleep(Duration(milliseconds: pollInterval)); + completer.complete(await waitOnTx(startTime, txId)); + } else { + completer.complete(false); + } + } + } catch (e) { + // Do not retry on definitive transaction errors + if (e is TxError) { + //rethrow; + completer.completeError(false); + } + + int nowTime = DateTime.now().millisecondsSinceEpoch; + if (nowTime - startTime < timeout) { + sleep(Duration(milliseconds: pollInterval)); + completer.complete(await waitOnTx(startTime, txId)); + } else { + print("last complete"); + completer.complete(false); + } + } + + return completer.future; + } + + Future> addCredits(dynamic principal, AddCreditsParam addCredits, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), AddCredits(addCredits), signer); + } + + Future> addValidator(dynamic principal, AddValidatorParam addValidator, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), AddValidator(addValidator), signer); + } + + Future> burnTokens(dynamic principal, BurnTokensParam burnTokens, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), BurnTokens(burnTokens), signer); + } + + Future> createDataAccount( + dynamic principal, CreateDataAccountParam createDataAccount, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), CreateDataAccount(createDataAccount), signer); + } + + Future> createIdentity(dynamic principal, CreateIdentityParam createIdentity, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), CreateIdentity(createIdentity), signer); + } + + Future> createKeyBook(dynamic principal, CreateKeyBookParam createKeyBook, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), CreateKeyBook(createKeyBook), signer); + } + + Future> createKeyPage(dynamic principal, CreateKeyPageParam createKeyPage, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), CreateKeyPage(createKeyPage), signer); + } + + Future> createToken(dynamic principal, CreateTokenParam createToken, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), CreateToken(createToken), signer); + } + + Future> createTokenAccount( + dynamic principal, CreateTokenAccountParam createTokenAccount, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), CreateTokenAccount(createTokenAccount), signer); + } + + Future> issueTokens(dynamic principal, IssueTokensParam issueTokens, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), IssueTokens(issueTokens), signer); + } + + Future> removeValidator(dynamic principal, RemoveValidatorArg removeValidator, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), RemoveValidator(removeValidator), signer); + } + + Future> sendTokens(dynamic principal, SendTokensParam sendTokens, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), SendTokens(sendTokens), signer); + } + + Future> updateAccountAuth( + dynamic principal, UpdateAccountAuthParam updateAccountAuthParam, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), UpdateAccountAuth(updateAccountAuthParam), signer); + } + + Future> updateKey(dynamic principal, UpdateKeyParam updateKey, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), UpdateKey(updateKey), signer); + } + + Future> updateKeyPage( + dynamic principal, UpdateKeyPageParam updateKeyPageParam, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), UpdateKeyPage(updateKeyPageParam), signer); + } + + Future> updateValidatorKey( + dynamic principal, UpdateValidatorKeyParam updateValidatorKey, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), UpdateValidatorKey(updateValidatorKey), signer); + } + + Future> writeData(dynamic principal, WriteDataParam writeData, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), WriteData(writeData), signer); + } + + Future> faucet(AccURL url) { + return call("faucet", { + "url": url.toString(), + }); + } + + Future> faucetSimple(String url) { + return call("faucet", { + "url": url, + }); + } + + Future> status() { + return call("status"); + } + + Future> version() { + return call("version"); + } + + Future> describe() { + return call("describe"); + } + + Future> metrics(String metric, int duration) { + return call("metrics", { + "metric": metric, + "duration": duration, + }); + } + + Future valueFromOracle() async { + int price = 0; + try { + final oracle = await queryAcmeOracle(); + price = oracle["result"]["values"]["oracle"]["price"]; + } catch (e) { + print("Not reacheable =====>>> $e"); + } + return price; + } + + Future> getAdiSlidingFee() async { + final networkParameters = await describe(); + List adiSlidingFeeTable = []; + var ds = networkParameters["result"]["values"]["globals"]["feeSchedule"]["createIdentitySliding"]; + adiSlidingFeeTable = List.from(ds); + return adiSlidingFeeTable; + } + + /// + /// "query-tx": m.QueryTx, + Future callGetTokenTransaction(String? txhash, [String? addr, bool? isLookupByUrl]) async { + var res; + if (isLookupByUrl != null) { + // NB: this is needed because Testnet not working + // with hash anymore but + res = await queryTxByUrl(txhash!); + } else { + res = await queryTx(txhash!); + } + + txModel.Transaction? tx; + if (res != null) { + var data = res['result']["data"]; + String? type = res['result']["type"]; + + print(type); + switch (type) { + case "syntheticTokenDeposit": + int amount = int.parse(res['result']["data"]["amount"]); + break; + case "syntheticDepositTokens": + String? txid = res['result']["txid"]; + String? from = res['result']["data"]["source"]; + String? to = res['result']["origin"]; + int amount = int.parse(res['result']["data"]["amount"]); + String? tokenUrl = res['result']["data"]["token"]; + + tx = txModel.Transaction("Outgoing", "send_token", txid, from, to, amount, tokenUrl); + break; + case "addCredits": + String amount = res['result']["data"]["amount"]; + int oracle = res['result']["data"]["oracle"]; + //int creditsVisual = (amount * oracle)! * 0.0000000001; // reverse formula + + String? txid = res['result']["data"]["txid"]; + String? from = res['result']["sponsor"]; + String? to = res['result']["data"]["recipient"]; + int creditsRawAmount = int.parse(amount); + LinkedHashMap sigs = res['result']["signatures"][0]; + int? ts = sigs["timestamp"]; + + tx = txModel.Transaction("Incoming", "add-credits", txid, from, to, creditsRawAmount, "credits"); + tx.created = DateTime.fromMicrosecondsSinceEpoch(ts!).millisecondsSinceEpoch; + break; + case "sendTokens": + String? txid = res['result']["txid"]; + String? from = res['result']["data"]["from"]; + List to = res['result']["data"]["to"]; + String? amount = ""; + String? urlRecepient = ""; + if (to != null) { + amount = to[0]["amount"]; + urlRecepient = to[0]["url"]; + } + LinkedHashMap sigs = res['result']["signatures"][0]; + int? ts = sigs["timestamp"]; + + tx = txModel.Transaction("Outgoing", "send_token", txid, from, urlRecepient, int.parse(amount!), "acc://"); + tx.created = DateTime.fromMicrosecondsSinceEpoch(ts!).millisecondsSinceEpoch; + break; + case "syntheticDepositCredits": + String? txid = res['result']["data"]["txid"]; + tx = txModel.Transaction("", "", txid, "", "", 0, ""); // use dummy structure for now + break; + case "createKeyPage": + String? txid = res['result']["txid"]; + String? from = res['result']["origin"]; + String? to = res['result']["data"]["url"]; + LinkedHashMap sigs = res['result']["signatures"][0]; + int? dateNonce = sigs["nonce"]; + + tx = txModel.Transaction("Outgoing", "", txid, from, to, 0, "ACME"); + tx.created = dateNonce; + + break; + case "acmeFaucet": + String? txid = res['result']["data"]["txid"]; + String? from = res['result']["data"]["from"]; + String? to = res['result']["data"]["url"]; + int amount = 1000000000; + LinkedHashMap sigs = res['result']["signatures"][0]; + int? ts = sigs["timestamp"]; + + tx = txModel.Transaction("Incoming", "", txid, from, to, amount, "ACME"); + tx.created = DateTime.fromMicrosecondsSinceEpoch(ts!).millisecondsSinceEpoch; + + break; + case "syntheticCreateChain": + String? txid = res['result']["data"]["txid"]; + String? sponsor = res['result']["sponsor"]; + String? origin = res['result']["origin"]; + LinkedHashMap sigs = res['result']["signatures"][0]; + int? dateNonce = sigs["Nonce"]; + + tx = txModel.Transaction("Outgoing", "", txid, sponsor, origin, 0, "ACME"); + tx.created = dateNonce; + break; + case "createIdentity": + // TODO: handle differently from "syntethicCreateChain" + String? txid = res['result']["data"]["txid"]; + tx = txModel.Transaction("", "", txid, "", "", 0, ""); // use dummy structure for now + break; + case "systemGenesis": + String? txid = res['result']["data"]["txid"]; + String? origin = res['result']["origin"]; + if (addr != null && addr != "") { + origin = addr; + } + + QueryPaginationForBlocks queryParams = QueryPaginationForBlocks(); + queryParams.start = 0; + queryParams.limit = 1; + + MinorBlocksQueryOptions queryFilter = MinorBlocksQueryOptions() + ..txFetchMode = 0 + ..blockFilterMode = 1; + + var majorBlocks = await queryMajorBlocks("acc://ACME", queryParams, queryFilter); // "acc://dn.acme" + var blockInfo = majorBlocks["result"]["items"][0]; + + var blockTime = blockInfo["majorBlockTime"]; + var blockTimeD = DateTime.parse(blockTime); + + tx = txModel.Transaction("Incoming", "system_genesis", txid, "acc://ACME", origin, 0, "acc://"); + tx.created = blockTimeD.millisecondsSinceEpoch; + break; + + case "updateAccountAuth": + String? txid = res['result']["txid"]; + String? sponsor = res['result']["sponsor"]; + String? origin = res['result']["origin"]; + LinkedHashMap sigs = res['result']["signatures"][0]; + int? dateNonce = sigs["timestamp"]; + String? status = res['result']["status"]["code"]; + + tx = txModel.Transaction("Outgoing", "update-account-auth", txid, sponsor, origin, 0, "ACME"); + tx.created = dateNonce; + tx.status = status; + break; + + case "createTokenAccount": + print(" create token account"); + String? txid = res['result']["txid"]; + String? sponsor = res['result']["sponsor"]; + String? origin = res['result']["origin"]; + LinkedHashMap sigs = res['result']["signatures"][0]; + int? dateNonce = sigs["timestamp"]; + int? dateNonce2 = DateTime.fromMicrosecondsSinceEpoch(dateNonce!).millisecondsSinceEpoch; + String? status = res['result']["status"]["code"]; + + tx = txModel.Transaction("Outgoing", "token-account-create", txid, sponsor, origin, 0, "ACME"); + tx.created = dateNonce; + tx.status = status; + break; + default: + print(" default handler"); + String? txid = res['result']["data"]["txid"]; + String? from = res['result']["data"]["from"]; + //ApiRespTxTo to = res.result["data"]["to"]; + LinkedHashMap dataTo = res['result']["data"]["to"][0]; + String? to = dataTo["url"]; + int? amount = dataTo["amount"]; + LinkedHashMap sigs = res['result']["signatures"][0]; + int? ts = sigs["timestamp"]; + + tx = txModel.Transaction("Outgoing", "", txid, from, to, amount, "ACME"); + tx.created = DateTime.fromMicrosecondsSinceEpoch(ts!).millisecondsSinceEpoch; + } + } + + return tx; + } + + /// + /// RPC: "query-tx-history" (in v1 - "token-account-history") + Future> callGetTokenTransactionHistory(String path) async { + QueryPagination queryPagination = QueryPagination(); + queryPagination.start = 0; + queryPagination.count = 100; + + TxHistoryQueryOptions txHistoryQueryOptions = TxHistoryQueryOptions(); + + final res = await queryTxHistory(path, queryPagination, txHistoryQueryOptions); + + // Collect transaction iteratively + List txs = []; + if (res != null) { + var records = res['result']["items"]; + + if (records == null) { + return []; + } + + for (var i = 0; i < records.length; i++) { + var tx = records[i]; + String? type = tx["type"]; + + switch (type) { + case "faucet": // that's faucet + String? txid = tx["txid"]; + String? amount = tx["data"]["amount"]; // AMOUNT INCOSISTENT, faucet returns String while other types int + String? token = tx["data"]["token"]; + var sigs = tx["signatures"]; + var sig = sigs[sigs.length - 1]; + int? ts = sig["timestamp"]; + + // if nothing that was a faucet + txModel.Transaction txl = txModel.Transaction("Incoming", "", txid, "", "", int.parse(amount!), "$token"); + + // NB: yes, can be + if (ts! == 1) { + txl.created = 1667304000 * 1000; + } else { + txl.created = DateTime.fromMicrosecondsSinceEpoch(ts).millisecondsSinceEpoch; + } + txs.add(txl); + break; + case "addCredits": + String? txid = tx["txid"]; + int? amountCredits = (tx["data"]["amount"] is String) + ? int.parse(tx["data"]["amount"]) + : tx["data"]["amount"]; // that's amount of credits + int amount = (amountCredits! * 0.01).toInt() * 10000; // in acmes + LinkedHashMap sigs = tx["signatures"][0]; + int? ts = sigs["timestamp"]; + + txModel.Transaction txl = txModel.Transaction("Incoming", "add-credits", txid, "", "", amount, "credits"); + txl.created = DateTime.fromMicrosecondsSinceEpoch(ts!).millisecondsSinceEpoch; + txs.add(txl); + break; + case "sendTokens": + String? txid = tx["txid"]; + String? from = tx["data"]["from"]; + List to = tx["data"]["to"]; + String? amount = ""; + String? urlRecepient = ""; + if (to != null) { + amount = to[0]["amount"]; + urlRecepient = to[0]["url"]; + } + LinkedHashMap sigs = tx["signatures"][0]; + int? ts = sigs["timestamp"]; + + txModel.Transaction txl = + txModel.Transaction("Outgoing", "send_token", txid, from, urlRecepient, int.parse(amount!), "acc://"); + txl.created = DateTime.fromMicrosecondsSinceEpoch(ts!).millisecondsSinceEpoch; + txs.add(txl); + break; + case "syntheticCreateChain": + String? txid = tx["txid"]; + int? amount = tx["data"]["amount"]; + String? token = tx["data"]["token"]; + + txModel.Transaction txl = txModel.Transaction("Outgoing", type!, txid, "", "", amount, "$token"); + txs.add(txl); + break; + case "burnTokens": + String? txid = tx["txid"]; + String? prod = tx["produced"][0]; + int? amount = int.parse(tx["data"]["amount"]); + String? token = prod!.split("@").last; + + txModel.Transaction txl = txModel.Transaction("Outgoing", type!, txid, "", "", amount, "$token"); + txs.add(txl); + break; + case "systemGenesis": + String? txid = tx["txid"]; + int? amount = tx["data"]["amount"]; + String? token = tx["data"]["token"]; + String? status = tx["status"]["code"]; + + QueryPaginationForBlocks queryParams = QueryPaginationForBlocks(); + queryParams.start = 0; + queryParams.limit = 1; + + MinorBlocksQueryOptions queryFilter = MinorBlocksQueryOptions() + ..txFetchMode = 0 + ..blockFilterMode = 1; + + var majorBlocks = await queryMajorBlocks("acc://dn.acme", queryParams, queryFilter); + var blockInfo = majorBlocks["result"]["items"][0]; + + var blockTime = blockInfo["majorBlockTime"]; + var blockTimeD = DateTime.parse(blockTime); + + txModel.Transaction txl = txModel.Transaction( + "Incoming", "system_genesis", txid, "acc://ACME", path, amount, "acc://ACME", status); + txl.created = blockTimeD.millisecondsSinceEpoch; + txs.add(txl); + break; + case "syntheticDepositTokens": + String? txid = tx["txid"]; + String? amountIn = tx["data"]["amount"]; + String? token = tx["data"]["token"]; + String? status = tx["status"]["code"]; + var sigs = tx["signatures"]; + var sig = sigs[sigs.length - 1]; + int? ts = sig["timestamp"]; + + String? from = tx["data"]["source"]; + + int amount = int.parse(amountIn!); + + txModel.Transaction txl = + txModel.Transaction("Incoming", "send_token", txid, from, path, amount, "$token", status); + if (ts! == 1) { + // Get Timestamp as time from block + int height = tx["status"]["received"]; + String bvnFrom = tx["status"]["sourceNetwork"]; + String bvn = tx["status"]["destinationNetwork"]; + String bvnDest = ""; + + QueryPaginationForBlocks queryParams = QueryPaginationForBlocks(); + queryParams.start = height; + queryParams.limit = 10; + + MinorBlocksQueryOptions queryFilter = MinorBlocksQueryOptions() + ..txFetchMode = 0 + ..blockFilterMode = 1; + + var minorBlocks = await queryMinorBlocks(bvn, queryParams, queryFilter); + var blockInfo = minorBlocks["result"]["items"][0]; //our block start + var blockTime = blockInfo["blockTime"]; + var blockTimeD = DateTime.parse(blockTime); + + txl.created = blockTimeD.millisecondsSinceEpoch; + } else { + txl.created = DateTime.fromMicrosecondsSinceEpoch(ts).millisecondsSinceEpoch; + } + + txs.add(txl); + break; + case "updateAccountAuth": + String? txid = tx["txid"]; + LinkedHashMap sigs = tx["signatures"][0]; + int? ts = sigs["timestamp"]; + String? sponsor = tx["sponsor"]; + String? origin = tx["origin"]; + + txModel.Transaction txl = + txModel.Transaction("Outgoing", "update-account-auth", txid, sponsor, origin, 0, "ACME"); + txl.created = DateTime.fromMicrosecondsSinceEpoch(ts!).millisecondsSinceEpoch; + txs.add(txl); + break; + case "createTokenAccount": + String? txid = tx["txid"]; + LinkedHashMap sigs = tx["signatures"][0]; + int? ts = sigs["timestamp"]; + String? sponsor = tx["sponsor"]; + String? origin = tx["origin"]; + + txModel.Transaction txl = + txModel.Transaction("Outgoing", "token-account-create", txid, sponsor, origin, 0, "ACME"); + txl.created = DateTime.fromMicrosecondsSinceEpoch(ts!).millisecondsSinceEpoch; + txs.add(txl); + break; + default: + String? txid = tx["txid"]; + int? amount = tx["data"]["amount"]; + String? token = tx["data"]["token"]; + + txModel.Transaction txl = txModel.Transaction("Outgoing", type!, txid, "", "", amount, "$token"); + txs.add(txl); + break; + } + } + } + + return txs; + } + + Future> factom(dynamic principal, FactomDataEntryParam factomParam, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), FactomDataEntry(factomParam), signer); + } + + Future> createLiteDataAccount( + dynamic principal, CreateLiteDataAccountParam createLiteDataAccountParam, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), CreateLiteDataAccount(createLiteDataAccountParam), signer); + } + + Future> writeDataTo(dynamic principal, WriteDataToParam writeDataToParam, TxSigner signer) { + return _execute(AccURL.toAccURL(principal), WriteDataTo(writeDataToParam), signer); + } +} diff --git a/lib/src/v3/enums.dart b/lib/src/v3/enums.dart new file mode 100644 index 0000000..dc95162 --- /dev/null +++ b/lib/src/v3/enums.dart @@ -0,0 +1,6 @@ + +enum EventType { + Error, + Block, + Globals, +} diff --git a/pubspec.yaml b/pubspec.yaml index 55c4099..90c11eb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,17 +9,17 @@ environment: dependencies: crypto: ^3.0.2 base58check: ^2.0.0 - bitcoin_bip44_ng: ^0.1.5 + bitcoin_bip44_ng: ^0.1.6 bip39: ^1.0.6 bs58: ^1.0.2 ed25519_edwards: ^0.3.1 hex: ^0.2.0 - http: ^0.13.4 + http: ^1.1.0 json_annotation: ^4.4.0 dartz: ^0.10.0 collection: ^1.16.0 + csv: ^5.0.2 dev_dependencies: - lints: ^1.0.0 - test: ^1.16.0 - test_html_builder: ^3.0.1 + lints: ^2.1.0 + test: ^1.24.7 \ No newline at end of file