Skip to content

Commit 04b66b3

Browse files
authored
Merge pull request #8346 from BitGo/fix/ada-unsigned-consolidation-CSHLD-135
test(sdk-coin-ada): adding unsigned consolidation tests for ada
2 parents 5428d17 + c3da0f3 commit 04b66b3

1 file changed

Lines changed: 150 additions & 0 deletions

File tree

  • modules/sdk-coin-ada/test/unit

modules/sdk-coin-ada/test/unit/ada.ts

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,156 @@ describe('ADA', function () {
982982
res.transactions.length.should.equal(2);
983983
});
984984

985+
it('should build unsigned consolidation recoveries for WRW (ADA only) and assert build response', async function () {
986+
const res = await basecoin.recoverConsolidations({
987+
bitgoKey: consolidationWrwUser.bitgoKey,
988+
startingScanIndex: 1,
989+
endingScanIndex: 4,
990+
});
991+
res.should.not.be.empty();
992+
res.txRequests.length.should.equal(2);
993+
994+
// Assert first consolidation txRequest structure
995+
const txRequest1 = res.txRequests[0];
996+
txRequest1.transactions.length.should.equal(1);
997+
const unsignedTx1 = txRequest1.transactions[0].unsignedTx;
998+
unsignedTx1.should.hasOwnProperty('serializedTx');
999+
unsignedTx1.should.hasOwnProperty('parsedTx');
1000+
unsignedTx1.should.hasOwnProperty('coinSpecific');
1001+
1002+
// Deserialize and verify inputs/outputs
1003+
const tx1 = new Transaction(basecoin);
1004+
tx1.fromRawTransaction(unsignedTx1.serializedTx);
1005+
const txJson1 = tx1.toJson();
1006+
const fee1 = Number(tx1.explainTransaction().fee.fee);
1007+
should.deepEqual(txJson1.inputs[0].transaction_id, testnetUTXO.UTXO_1.tx_hash);
1008+
should.deepEqual(txJson1.inputs[0].transaction_index, testnetUTXO.UTXO_1.tx_index);
1009+
should.deepEqual(txJson1.outputs[0].address, baseAddr);
1010+
should.deepEqual(Number(txJson1.outputs[0].amount) + fee1, testnetUTXO.UTXO_1.value);
1011+
1012+
// parsedTx inputs/outputs must be present and carry correct address
1013+
const parsedTx1Inputs = unsignedTx1.parsedTx.inputs;
1014+
parsedTx1Inputs.length.should.equal(1);
1015+
should.deepEqual(parsedTx1Inputs[0].address, consolidationWrwUser.walletAddress2);
1016+
const parsedTx1Outputs = unsignedTx1.parsedTx.outputs;
1017+
parsedTx1Outputs.length.should.be.greaterThan(0);
1018+
should.deepEqual(parsedTx1Outputs[0].address, baseAddr);
1019+
1020+
// Assert second consolidation txRequest structure
1021+
const txRequest2 = res.txRequests[1];
1022+
const unsignedTx2 = txRequest2.transactions[0].unsignedTx;
1023+
unsignedTx2.should.hasOwnProperty('serializedTx');
1024+
1025+
const tx2 = new Transaction(basecoin);
1026+
tx2.fromRawTransaction(unsignedTx2.serializedTx);
1027+
const txJson2 = tx2.toJson();
1028+
const fee2 = Number(tx2.explainTransaction().fee.fee);
1029+
should.deepEqual(txJson2.inputs[0].transaction_id, testnetUTXO.UTXO_2.tx_hash);
1030+
should.deepEqual(txJson2.inputs[0].transaction_index, testnetUTXO.UTXO_2.tx_index);
1031+
should.deepEqual(txJson2.outputs[0].address, baseAddr);
1032+
should.deepEqual(Number(txJson2.outputs[0].amount) + fee2, testnetUTXO.UTXO_2.value);
1033+
1034+
// lastScanIndex must be set in coinSpecific of the last txRequest
1035+
const lastCoinSpecific = unsignedTx2.coinSpecific;
1036+
lastCoinSpecific.should.hasOwnProperty('lastScanIndex');
1037+
lastCoinSpecific.lastScanIndex.should.equal(3);
1038+
});
1039+
1040+
it('should build unsigned consolidation recoveries for WRW (ADA + Token) and assert build response', async function () {
1041+
// Override walletAddress2 to return ADA+Token UTXOs
1042+
sandBox.restore();
1043+
const callBack2 = sandBox.stub(Ada.prototype, 'getDataFromNode' as keyof Ada);
1044+
callBack2
1045+
.withArgs('address_info', { _addresses: [consolidationWrwUser.walletAddress1] })
1046+
.resolves(endpointResponses.addressInfoResponse.ZeroUTXO);
1047+
callBack2
1048+
.withArgs('address_info', { _addresses: [consolidationWrwUser.walletAddress2] })
1049+
.resolves(endpointResponses.addressInfoResponse.ADAAndTokenUTXOs);
1050+
callBack2
1051+
.withArgs('address_info', { _addresses: [consolidationWrwUser.walletAddress3] })
1052+
.resolves(endpointResponses.addressInfoResponse.ZeroUTXO);
1053+
callBack2.withArgs('tip').resolves(endpointResponses.tipInfoResponse);
1054+
1055+
const tokenPolicyId = '2533cca6eb42076e144e9f2772c390dece9fce173bc38c72294b3924';
1056+
const tokenEncodedAssetName = '5741544552';
1057+
const tokenQuantity = '111';
1058+
const minADAForToken = 1500000;
1059+
1060+
const res = await basecoin.recoverConsolidations({
1061+
bitgoKey: consolidationWrwUser.bitgoKey,
1062+
startingScanIndex: 1,
1063+
endingScanIndex: 4,
1064+
});
1065+
res.should.not.be.empty();
1066+
res.txRequests.length.should.equal(1);
1067+
1068+
const unsignedTx = res.txRequests[0].transactions[0].unsignedTx;
1069+
unsignedTx.should.hasOwnProperty('serializedTx');
1070+
1071+
const tx = new Transaction(basecoin);
1072+
tx.fromRawTransaction(unsignedTx.serializedTx);
1073+
const txJson = tx.toJson();
1074+
1075+
// Two inputs: ADA UTXO + Token UTXO
1076+
txJson.inputs.length.should.equal(2);
1077+
should.deepEqual(txJson.inputs[0].transaction_id, testnetUTXO.UTXO_1.tx_hash);
1078+
should.deepEqual(txJson.inputs[1].transaction_id, testnetUTXO.UTXO_TOKEN.tx_hash);
1079+
1080+
// Two outputs: token output (with multiAssets) + pure ADA change to base address
1081+
txJson.outputs.length.should.equal(2);
1082+
const tokenOutput = txJson.outputs.find((o) => o.multiAssets !== undefined);
1083+
should.exist(tokenOutput);
1084+
should.deepEqual(tokenOutput!.address, baseAddr);
1085+
should.deepEqual(Number(tokenOutput!.amount), minADAForToken);
1086+
const expectedPolicyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(tokenPolicyId, 'hex'));
1087+
const expectedAssetName = CardanoWasm.AssetName.new(Buffer.from(tokenEncodedAssetName, 'hex'));
1088+
(tokenOutput!.multiAssets as CardanoWasm.MultiAsset)
1089+
.get_asset(expectedPolicyId, expectedAssetName)
1090+
.to_str()
1091+
.should.equal(tokenQuantity);
1092+
1093+
const adaOutput = txJson.outputs.find((o) => o.multiAssets === undefined);
1094+
should.exist(adaOutput);
1095+
should.deepEqual(adaOutput!.address, baseAddr);
1096+
const fee = Number(tx.explainTransaction().fee.fee);
1097+
const totalBalance = testnetUTXO.UTXO_1.value + testnetUTXO.UTXO_TOKEN.value;
1098+
should.deepEqual(Number(adaOutput!.amount), totalBalance - minADAForToken - fee);
1099+
1100+
// parsedTx inputs must carry multiAssets for the token UTXO
1101+
const parsedTxInputs = unsignedTx.parsedTx.inputs as {
1102+
address: string;
1103+
valueString: string;
1104+
multiAssets?: { policy_id: string; asset_name: string; quantity: string }[];
1105+
}[];
1106+
parsedTxInputs.length.should.equal(1);
1107+
should.deepEqual(parsedTxInputs[0].address, consolidationWrwUser.walletAddress2);
1108+
should.exist(parsedTxInputs[0].multiAssets);
1109+
parsedTxInputs[0].multiAssets!.length.should.equal(1);
1110+
should.deepEqual(parsedTxInputs[0].multiAssets![0].policy_id, tokenPolicyId);
1111+
should.deepEqual(parsedTxInputs[0].multiAssets![0].asset_name, tokenEncodedAssetName);
1112+
should.deepEqual(parsedTxInputs[0].multiAssets![0].quantity, tokenQuantity);
1113+
1114+
// parsedTx outputs must carry multiAssets for the token output
1115+
const parsedTxOutputs = unsignedTx.parsedTx.outputs as {
1116+
address: string;
1117+
valueString: string;
1118+
multiAssets?: { policy_id: string; asset_name: string; quantity: string }[];
1119+
}[];
1120+
const parsedTokenOutput = parsedTxOutputs.find((o) => o.multiAssets !== undefined);
1121+
should.exist(parsedTokenOutput);
1122+
parsedTokenOutput!.multiAssets!.length.should.equal(1);
1123+
should.deepEqual(parsedTokenOutput!.multiAssets![0].policy_id, tokenPolicyId);
1124+
should.deepEqual(parsedTokenOutput!.multiAssets![0].asset_name, tokenEncodedAssetName);
1125+
should.deepEqual(parsedTokenOutput!.multiAssets![0].quantity, tokenQuantity);
1126+
// pure ADA output must not have multiAssets
1127+
const parsedAdaOutput = parsedTxOutputs.find((o) => o.multiAssets === undefined);
1128+
should.exist(parsedAdaOutput);
1129+
1130+
// lastScanIndex in coinSpecific of the last txRequest
1131+
unsignedTx.coinSpecific.should.hasOwnProperty('lastScanIndex');
1132+
unsignedTx.coinSpecific.lastScanIndex.should.equal(3);
1133+
});
1134+
9851135
it('should throw error if all addresses have balance less than 1 ADA', async function () {
9861136
sandBox.restore();
9871137
const callBack = sandBox.stub(Ada.prototype, 'getDataFromNode' as keyof Ada);

0 commit comments

Comments
 (0)