transactionEnvelopeXdrBase64FromTxRep method
- String txRep
returns a base64 encoded transaction envelope xdr by parsing txRep
.
Implementation
static String transactionEnvelopeXdrBase64FromTxRep(String txRep) {
if (txRep == null) {
throw Exception('txRep can not be null');
}
List<String> lines = txRep.split('\n'); //TODO: handle newline within string
Map<String, String> map = Map<String, String>();
for (String line in lines) {
var parts = line.split(':');
if (parts.length > 1) {
String key = parts[0].trim();
String value = parts.sublist(1).join(':').trim();
map.addAll({key: value});
}
}
String prefix = 'tx.';
bool isFeeBump = _removeComment(map['type']) == 'ENVELOPE_TYPE_TX_FEE_BUMP';
int feeBumpFee;
String feeBumpSource = _removeComment(map['feeBump.tx.feeSource']);
if (isFeeBump) {
prefix = 'feeBump.tx.innerTx.tx.';
String feeBumpFeeStr = _removeComment(map['feeBump.tx.fee']);
if (feeBumpFeeStr == null) {
throw Exception('missing feeBump.tx.fee');
}
try {
feeBumpFee = int.parse(feeBumpFeeStr);
} catch (e) {
throw Exception('invalid feeBump.tx.fee');
}
if (feeBumpFee == null) {
throw Exception('invalid feeBump.tx.fee');
}
if (feeBumpSource == null) {
throw Exception('missing feeBump.tx.feeSource');
}
KeyPair feeBumpSourceKeyPair;
try {
feeBumpSourceKeyPair = KeyPair.fromAccountId(feeBumpSource);
} catch (e) {
throw Exception('invalid feeBump.tx.feeSource');
}
if (feeBumpSourceKeyPair == null) {
throw Exception('invalid feeBump.tx.feeSource');
}
}
String sourceAccountId = _removeComment(map['${prefix}sourceAccount']);
if (sourceAccountId == null) {
throw Exception('missing ${prefix}sourceAccount');
}
String feeStr = _removeComment(map['${prefix}fee']);
int fee;
if (feeStr == null) {
throw Exception('missing ${prefix}fee');
} else {
try {
fee = int.parse(feeStr);
} catch (e) {
throw Exception('invalid ${prefix}fee');
}
}
if (fee == null) {
throw Exception('invalid ${prefix}fee');
}
String seqNr = _removeComment(map['${prefix}seqNum']);
int sequenceNumber;
if (seqNr == null) {
throw Exception('missing ${prefix}seqNum');
} else {
try {
sequenceNumber = int.parse(seqNr);
} catch (e) {
throw Exception('invalid ${prefix}seqNum');
}
}
if (sequenceNumber == null) {
throw Exception('invalid ${prefix}seqNum');
}
if (sourceAccountId == null) {
throw Exception('invalid ${prefix}sourceAccount');
}
try {
KeyPair.fromAccountId(sourceAccountId);
} catch (e) {
throw Exception('invalid ${prefix}sourceAccount');
}
MuxedAccount mux = MuxedAccount.fromAccountId(sourceAccountId);
Account sourceAccount = Account(mux.ed25519AccountId, sequenceNumber - 1,
muxedAccountMed25519Id: mux.id);
TransactionBuilder txBuilder = TransactionBuilder(sourceAccount);
// TimeBounds
if (_removeComment(map['${prefix}timeBounds._present']) == 'true' &&
map['${prefix}timeBounds.minTime'] != null &&
map['${prefix}timeBounds.maxTime'] != null) {
try {
int minTime =
int.parse(_removeComment(map['${prefix}timeBounds.minTime']));
int maxTime =
int.parse(_removeComment(map['${prefix}timeBounds.maxTime']));
TimeBounds timeBounds = TimeBounds(minTime, maxTime);
txBuilder.addTimeBounds(timeBounds);
} catch (e) {
throw Exception('invalid ${prefix}timeBounds');
}
} else if (_removeComment(map['${prefix}timeBounds._present']) == 'true') {
throw Exception('invalid ${prefix}timeBounds');
}
// Memo
String memoType = _removeComment(map['${prefix}memo.type']);
if (memoType == null) {
throw Exception('missing ${prefix}memo.type');
}
try {
if (memoType == 'MEMO_TEXT' && map['${prefix}memo.text'] != null) {
txBuilder.addMemo(MemoText(
_removeComment(map['${prefix}memo.text']).replaceAll('"', '')));
} else if (memoType == 'MEMO_ID' && map['${prefix}memo.id'] != null) {
txBuilder.addMemo(
MemoId(int.parse(_removeComment(map['${prefix}memo.id']))));
} else if (memoType == 'MEMO_HASH' && map['${prefix}memo.hash'] != null) {
txBuilder.addMemo(MemoHash(
Util.hexToBytes(_removeComment(map['${prefix}memo.hash']))));
} else if (memoType == 'MEMO_RETURN' &&
map['${prefix}memo.return'] != null) {
txBuilder.addMemo(
MemoReturnHash.string(_removeComment(map['${prefix}memo.return'])));
} else {
txBuilder.addMemo(MemoNone());
}
} catch (e) {
throw Exception('invalid ${prefix}memo');
}
// Operations
String operationsLen = _removeComment(map['${prefix}operations.len']);
if (operationsLen == null) {
throw Exception('missing ${prefix}operations.len');
}
int nrOfOperations;
try {
nrOfOperations = int.parse(operationsLen);
} catch (e) {
throw Exception('invalid ${prefix}operations.len');
}
if (nrOfOperations > 100) {
throw Exception('invalid ${prefix}operations.len - greater than 100');
}
for (int i = 0; i < nrOfOperations; i++) {
Operation operation = _getOperation(i, map, prefix);
if (operation != null) {
txBuilder.addOperation(operation);
}
}
int maxOperationFee = (fee.toDouble() / nrOfOperations.toDouble()).round();
txBuilder.setMaxOperationFee(maxOperationFee);
AbstractTransaction transaction = txBuilder.build();
// Signatures
prefix = isFeeBump ? 'feeBump.tx.innerTx.' : "";
String signaturesLen = _removeComment(map['${prefix}signatures.len']);
if (signaturesLen != null) {
int nrOfSignatures;
try {
nrOfSignatures = int.parse(signaturesLen);
} catch (e) {
throw Exception('invalid ${prefix}signatures.len');
}
if (nrOfSignatures > 20) {
throw Exception('invalid ${prefix}signatures.len - greater than 20');
}
List<XdrDecoratedSignature> signatures = List<XdrDecoratedSignature>();
for (int i = 0; i < nrOfSignatures; i++) {
XdrDecoratedSignature signature = _getSignature(i, map, prefix);
if (signature != null) {
signatures.add(signature);
}
}
transaction.signatures = signatures;
}
if (isFeeBump) {
FeeBumpTransactionBuilder builder =
FeeBumpTransactionBuilder(transaction);
int baseFee =
(feeBumpFee.toDouble() / (nrOfOperations + 1).toDouble()).round();
builder.setBaseFee(baseFee);
builder.setMuxedFeeAccount(MuxedAccount.fromAccountId(feeBumpSource));
FeeBumpTransaction feeBumpTransaction = builder.build();
String fbSignaturesLen = _removeComment(map['feeBump.signatures.len']);
if (fbSignaturesLen != null) {
int nrOfFbSignatures;
try {
nrOfFbSignatures = int.parse(fbSignaturesLen);
} catch (e) {
throw Exception('invalid feeBump.signatures.len');
}
if (nrOfFbSignatures > 20) {
throw Exception('invalid feeBump.signatures.len - greater than 20');
}
List<XdrDecoratedSignature> fbSignatures =
List<XdrDecoratedSignature>();
for (int i = 0; i < nrOfFbSignatures; i++) {
XdrDecoratedSignature fbSignature = _getSignature(i, map, 'feeBump.');
if (fbSignature != null) {
fbSignatures.add(fbSignature);
}
}
feeBumpTransaction.signatures = fbSignatures;
return feeBumpTransaction.toEnvelopeXdrBase64();
}
}
return transaction.toEnvelopeXdrBase64();
}