Skip to content

Commit 6269f8c

Browse files
committed
fix(ada): providing unsigned sweep support for WRW
Ticket: CSHLD-134
1 parent 6f82462 commit 6269f8c

3 files changed

Lines changed: 114 additions & 9 deletions

File tree

modules/sdk-coin-ada/src/ada.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -507,13 +507,18 @@ export class Ada extends BaseCoin {
507507
value: new BigNumber(output.amount).toNumber(),
508508
},
509509
];
510-
const outputs = [
511-
{
512-
address: output.address,
513-
valueString: output.amount,
514-
coinName: walletCoin,
515-
},
516-
];
510+
const outputs = (
511+
parsedTx.outputs as {
512+
amount: string;
513+
address: string;
514+
tokenTransfers?: { policyId: string; assetName: string; quantity: string }[];
515+
}[]
516+
).map((o) => ({
517+
address: o.address,
518+
valueString: o.amount,
519+
coinName: walletCoin,
520+
...(o.tokenTransfers && { tokenTransfers: o.tokenTransfers }),
521+
}));
517522
const spendAmount = output.amount;
518523
const completedParsedTx = { inputs: inputs, outputs: outputs, spendAmount: spendAmount, type: '' };
519524
const fee = new BigNumber((parsedTx.fee as { fee: string }).fee);

modules/sdk-coin-ada/src/lib/transaction.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,43 @@ export interface TxData {
8787
pledgeDetails?: PledgeDetails;
8888
}
8989

90+
function extractTokenTransfers(
91+
multiAssets: CardanoWasm.MultiAsset | Asset | undefined
92+
): Array<{ policyId: string; assetName: string; quantity: string }> | undefined {
93+
if (!multiAssets) return undefined;
94+
95+
if (!(multiAssets instanceof CardanoWasm.MultiAsset)) {
96+
return [
97+
{
98+
policyId: multiAssets.policy_id,
99+
assetName:
100+
(multiAssets as Asset & { encoded_asset_name?: string }).encoded_asset_name ?? multiAssets.asset_name,
101+
quantity: multiAssets.quantity,
102+
},
103+
];
104+
}
105+
106+
const transfers: Array<{ policyId: string; assetName: string; quantity: string }> = [];
107+
const scriptHashes = multiAssets.keys();
108+
for (let i = 0; i < scriptHashes.len(); i++) {
109+
const scriptHash = scriptHashes.get(i);
110+
const assets = multiAssets.get(scriptHash);
111+
if (!assets) continue;
112+
const assetNames = assets.keys();
113+
for (let j = 0; j < assetNames.len(); j++) {
114+
const assetName = assetNames.get(j);
115+
const quantity = assets.get(assetName);
116+
if (!quantity) continue;
117+
transfers.push({
118+
policyId: Buffer.from(scriptHash.to_bytes()).toString('hex'),
119+
assetName: Buffer.from(assetName.name()).toString('hex'),
120+
quantity: quantity.to_str(),
121+
});
122+
}
123+
}
124+
return transfers.length > 0 ? transfers : undefined;
125+
}
126+
90127
export class Transaction extends BaseTransaction {
91128
private _transaction: CardanoWasm.Transaction;
92129
private _fee: string;
@@ -381,7 +418,11 @@ export class Transaction extends BaseTransaction {
381418

382419
/** @inheritdoc */
383420
explainTransaction(): {
384-
outputs: { amount: string; address: string }[];
421+
outputs: {
422+
amount: string;
423+
address: string;
424+
tokenTransfers?: Array<{ policyId: string; assetName: string; quantity: string }>;
425+
}[];
385426
certificates: Cert[];
386427
changeOutputs: string[];
387428
outputAmount: string;
@@ -414,7 +455,11 @@ export class Transaction extends BaseTransaction {
414455
return {
415456
displayOrder,
416457
id: txJson.id,
417-
outputs: txJson.outputs.map((o) => ({ address: o.address, amount: o.amount })),
458+
outputs: txJson.outputs.map((o) => ({
459+
address: o.address,
460+
amount: o.amount,
461+
...(extractTokenTransfers(o.multiAssets) && { tokenTransfers: extractTokenTransfers(o.multiAssets) }),
462+
})),
418463
outputAmount: outputAmount,
419464
changeOutputs: [],
420465
changeAmount: '0',

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,61 @@ describe('ADA', function () {
674674
should.deepEqual(Number(txJson.outputs[0].amount) + fee, testnetUTXO.UTXO_1.value);
675675
});
676676

677+
it('should recover ADA plus token UTXOs - token and ADA both appear in outputs (unsigned sweep)', async function () {
678+
callBack
679+
.withArgs('address_info', { _addresses: [wrwUser.walletAddress0] })
680+
.resolves(endpointResponses.addressInfoResponse.ADAAndTokenUTXOs);
681+
682+
const res = await basecoin.recover({
683+
bitgoKey: wrwUser.bitgoKey,
684+
recoveryDestination: destAddr,
685+
});
686+
res.should.not.be.empty();
687+
const unsignedTx = res.txRequests[0].transactions[0].unsignedTx;
688+
unsignedTx.should.hasOwnProperty('serializedTx');
689+
690+
const tx = new Transaction(basecoin);
691+
tx.fromRawTransaction(unsignedTx.serializedTx);
692+
const txJson = tx.toJson();
693+
694+
txJson.inputs.length.should.equal(2);
695+
should.deepEqual(txJson.inputs[0].transaction_id, testnetUTXO.UTXO_1.tx_hash);
696+
should.deepEqual(txJson.inputs[1].transaction_id, testnetUTXO.UTXO_TOKEN.tx_hash);
697+
698+
txJson.outputs.length.should.equal(2);
699+
700+
const tokenPolicyId = '2533cca6eb42076e144e9f2772c390dece9fce173bc38c72294b3924';
701+
const tokenEncodedAssetName = '5741544552';
702+
const tokenQuantity = '111';
703+
const minADAForToken = 1500000;
704+
705+
const tokenOutput = txJson.outputs.find((o) => o.multiAssets !== undefined);
706+
should.exist(tokenOutput);
707+
should.deepEqual(tokenOutput!.address, destAddr);
708+
should.deepEqual(Number(tokenOutput!.amount), minADAForToken);
709+
const expectedPolicyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(tokenPolicyId, 'hex'));
710+
const expectedAssetName = CardanoWasm.AssetName.new(Buffer.from(tokenEncodedAssetName, 'hex'));
711+
(tokenOutput!.multiAssets as CardanoWasm.MultiAsset)
712+
.get_asset(expectedPolicyId, expectedAssetName)
713+
.to_str()
714+
.should.equal(tokenQuantity);
715+
716+
const adaOutput = txJson.outputs.find((o) => o.multiAssets === undefined);
717+
should.exist(adaOutput);
718+
should.deepEqual(adaOutput!.address, destAddr);
719+
const fee = Number(tx.explainTransaction().fee.fee);
720+
const totalBalance = testnetUTXO.UTXO_1.value + testnetUTXO.UTXO_TOKEN.value;
721+
should.deepEqual(Number(adaOutput!.amount), totalBalance - minADAForToken - fee);
722+
723+
const explained = tx.explainTransaction();
724+
const explainedTokenOutput = explained.outputs.find((o) => o.tokenTransfers !== undefined);
725+
should.exist(explainedTokenOutput);
726+
explainedTokenOutput!.tokenTransfers!.length.should.equal(1);
727+
should.deepEqual(explainedTokenOutput!.tokenTransfers![0].policyId, tokenPolicyId);
728+
should.deepEqual(explainedTokenOutput!.tokenTransfers![0].assetName, tokenEncodedAssetName);
729+
should.deepEqual(explainedTokenOutput!.tokenTransfers![0].quantity, tokenQuantity);
730+
});
731+
677732
it('should recover ADA plus token UTXOs - token and ADA both appear in outputs (signed)', async function () {
678733
callBack
679734
.withArgs('address_info', { _addresses: [wrwUser.walletAddress0] })

0 commit comments

Comments
 (0)