collectHashes method

  1. @visibleForTesting
List<String>? collectHashes(
  1. String namespace,
  2. JsonRpcResponse response
)

Implementation

@visibleForTesting
List<String>? collectHashes(String namespace, JsonRpcResponse response) {
  if (response.result == null || response.error != null) {
    return null;
  }

  switch (namespace) {
    case 'solana':
      try {
        final result = (response.result as Map<String, dynamic>);
        // if contain signature it's either solana_signTransaction or solana_signTransaction
        final signature = ReownCoreUtils.recursiveSearchForMapKey(
          result,
          'signature',
        );
        if (signature != null) {
          return <String>[...signature];
        }
        // if contain transactions it's solana_signAllTransactions
        final transactions = ReownCoreUtils.recursiveSearchForMapKey(
          result,
          'transactions',
        );
        if (transactions != null) {
          // Decode transactions and extract signature to send as TVF data
          final signatures = (transactions as List).map((encodedTx) {
            return SolanaChainUtils.extractSolanaSignature(encodedTx);
          }).toList();
          return signatures;
        }
      } catch (e) {
        core.logger.e('[$runtimeType] _tvf data: solana, $e');
      }
      return null;
    case 'xrpl':
      try {
        final result = (response.result as Map<String, dynamic>);
        final txHash = ReownCoreUtils.recursiveSearchForMapKey(
          result,
          'hash',
        );
        if (txHash != null) {
          return <String>[txHash];
        }
      } catch (e) {
        core.logger.e('[$runtimeType] _tvf data: xrpl, $e');
      }
      return null;
    case 'algo':
      try {
        final result = (response.result as List);
        final txHashesList = AlgorandChainUtils.calculateTxIDs(result);
        return <String>[...txHashesList];
      } catch (e) {
        core.logger.e('[$runtimeType] _tvf data: algo, $e');
      }
      return null;
    case 'sui':
      try {
        final result = (response.result as Map<String, dynamic>);
        // if sui_signAndExecuteTransaction then it'll contain digest
        final digest = ReownCoreUtils.recursiveSearchForMapKey(
          result,
          'digest',
        );
        if (digest != null) {
          return <String>[digest];
        }
        // if sui_signTransaction the it'll contain signature and transactionBytes
        final signature = ReownCoreUtils.recursiveSearchForMapKey(
          result,
          'signature',
        );
        if (signature != null) {
          final transactionBytes = ReownCoreUtils.recursiveSearchForMapKey(
            result,
            'transactionBytes',
          );
          if (transactionBytes != null) {
            final computedHash = SuiChainUtils.getSuiDigestFromEncodedTx(
              transactionBytes,
            );
            return <String>[computedHash.toString()];
          }
        }
      } catch (e) {
        core.logger.e('[$runtimeType] _tvf data: sui, $e');
      }
      return null;
    case 'tron':
      try {
        final result = (response.result as Map<String, dynamic>);
        final txID = ReownCoreUtils.recursiveSearchForMapKey(result, 'txID');
        if (txID != null) {
          return <String>[txID.toString()];
        }
      } catch (e) {
        core.logger.e('[$runtimeType] _tvf data: tron, $e');
      }
      return null;
    case 'hedera':
      try {
        final result = (response.result as Map<String, dynamic>);
        final transactionId = ReownCoreUtils.recursiveSearchForMapKey(
          result,
          'transactionId',
        );
        if (transactionId != null) {
          return <String>[transactionId.toString()];
        }
      } catch (e) {
        core.logger.e('[$runtimeType] _tvf data: hedera, $e');
      }
      return null;
    case 'bip122':
      try {
        final result = (response.result as Map<String, dynamic>);
        final txid = ReownCoreUtils.recursiveSearchForMapKey(result, 'txid');
        return <String>[txid.toString()];
      } catch (e) {
        core.logger.e('[$runtimeType] _tvf data: bip122, $e');
      }
      return null;
    case 'stacks':
      try {
        final result = (response.result as Map<String, dynamic>);
        final txid = ReownCoreUtils.recursiveSearchForMapKey(result, 'txid');
        return <String>[txid.toString()];
      } catch (e) {
        core.logger.e('[$runtimeType] _tvf data: stacks, $e');
      }
      return null;
    case 'near':
      try {
        final result = NearChainUtils.parseResponse(response.result);
        final hash = NearChainUtils.computeNearHashFromTxBytes(result);
        return <String>[hash];
      } catch (e) {
        core.logger.e('[$runtimeType] _tvf data: near, $e');
      }
      return null;
    case 'polkadot':
      try {
        final result = (response.result as Map<String, dynamic>);
        final signature = ReownCoreUtils.recursiveSearchForMapKey(
          result,
          'signature',
        );
        if (signature != null) {
          final id = response.id;
          final requestParams = pendingTVFRequests[id]!.requestParams;
          final params = requestParams as Map<String, dynamic>;
          final payload = ReownCoreUtils.recursiveSearchForMapKey(
            params,
            'transactionPayload',
          );
          final ss58Address = ReownCoreUtils.recursiveSearchForMapKey(
            params,
            'address',
          );
          final publicKey = PolkadotChainUtils.ss58AddressToPublicKey(
            ss58Address,
          );
          final extrinsic = PolkadotChainUtils.addSignatureToExtrinsic(
            publicKey: Uint8List.fromList(publicKey),
            hexSignature: signature,
            payload: payload,
          );
          final signedHex = hex.encode(extrinsic);
          final hash = PolkadotChainUtils.deriveExtrinsicHash(signedHex);
          return <String>[hash];
        }
      } catch (e) {
        core.logger.e('[$runtimeType] _tvf data: polkadot, $e');
      }
      return null;
    case 'cosmos':
      try {
        // only cosmos_signDirect and cosmos_signAmino has a result of type Map
        // cosmos_getAccounts would respond with a List but we don't want to parse this method
        // wrapping it with a try/catch as for other methods is enough
        final result = (response.result as Map<String, dynamic>);
        final signature = ReownCoreUtils.recursiveSearchForMapKey(
          result,
          'signature',
        );
        if (signature != null) {
          final bodyBytes = ReownCoreUtils.recursiveSearchForMapKey(
            result,
            'bodyBytes',
          );
          final authInfoBytes = ReownCoreUtils.recursiveSearchForMapKey(
            result,
            'authInfoBytes',
          );
          final hash = CosmosUtils.computeTxHash(
            bodyBytesBase64: bodyBytes,
            authInfoBytesBase64: authInfoBytes,
            signatureBase64: signature['signature'],
          );
          return <String>[hash];
        }
      } catch (e) {
        core.logger.e('[$runtimeType] collectHashes: cosmos, $e');
      }
      return null;
    default:
      // default to EVM
      try {
        if (response.result is Map) {
          // wallet_sendCalls 2.0.0
          final id = ReownCoreUtils.recursiveSearchForMapKey(
            response.result,
            'id',
          );
          if (id != null) {
            final transactionHashes =
                (ReownCoreUtils.recursiveSearchForMapKey(
                          response.result,
                          'transactionHashes',
                        )
                        as List)
                    .map((e) => e.toString())
                    .toList();
            return <String>[id.toString(), ...transactionHashes];
          }
          return null;
        }
        return <String>[response.result.toString()];
      } catch (e) {
        core.logger.e('[$runtimeType] _collectHashes: evm, $e');
      }
      return null;
  }
}