Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion modules/sdk-coin-ada/src/lib/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export class Transaction extends BaseTransaction {
private _transaction: CardanoWasm.Transaction;
private _fee: string;
private _pledgeDetails?: PledgeDetails;
private _changeAddress?: string;

constructor(coinConfig: Readonly<CoinConfig>) {
super(coinConfig);
Expand Down Expand Up @@ -391,7 +392,7 @@ export class Transaction extends BaseTransaction {

/** @inheritdoc */
explainTransaction(): {
outputs: { amount: string; address: string; multiAssets?: Asset[] }[];
outputs: { amount: string; address: string; multiAssets?: Asset[]; change?: boolean }[];
certificates: Cert[];
changeOutputs: string[];
outputAmount: string;
Expand Down Expand Up @@ -426,10 +427,12 @@ export class Transaction extends BaseTransaction {
id: txJson.id,
outputs: txJson.outputs.map((o) => {
const multiAssets = Transaction.parseMultiAssets(o.multiAssets as CardanoWasm.MultiAsset | undefined);
const isChange = this._changeAddress !== undefined && o.address === this._changeAddress;
return {
address: o.address,
amount: o.amount,
...(multiAssets && { multiAssets }),
...(isChange && { change: true }),
};
}),
outputAmount: outputAmount,
Expand Down Expand Up @@ -485,6 +488,14 @@ export class Transaction extends BaseTransaction {
fee(fee: string) {
this._fee = fee;
}

set changeAddress(address: string) {
this._changeAddress = address;
}

get changeAddress(): string | undefined {
return this._changeAddress;
}
}

export interface SponsorshipInfo {
Expand Down
9 changes: 9 additions & 0 deletions modules/sdk-coin-ada/src/lib/transactionBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
this.setMutableSenderAssetList();
this.addOutputs(outputs);
this._transaction.transaction = this.prepareAdaTransactionDraft(inputs, outputs, true);
if (this._changeAddress) {
this._transaction.changeAddress = this._changeAddress;
}
return this.transaction;
}

Expand Down Expand Up @@ -573,6 +576,9 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {

const finalOutputs = this.buildExplicitOutputsCollection(this._fee);
this._transaction.transaction = this.prepareAdaTransactionDraft(inputs, finalOutputs, true);
if (this._changeAddress) {
this._transaction.changeAddress = this._changeAddress;
}
return this.transaction;
}

Expand Down Expand Up @@ -924,6 +930,9 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
});
witnessSet.set_vkeys(vkeyWitnesses);
this._transaction.transaction = CardanoWasm.Transaction.new(txRaw, witnessSet);
if (this._changeAddress) {
this._transaction.changeAddress = this._changeAddress;
}
return this.transaction;
}

Expand Down
67 changes: 67 additions & 0 deletions modules/sdk-coin-ada/test/unit/transactionBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -549,4 +549,71 @@ describe('ADA Transaction Builder', async () => {
// console.log(err);
// }
// });

describe('explainTransaction change output marking', () => {
it('should mark the change output with change: true for a shelley send tx', async () => {
const txBuilder = factory.getTransferBuilder();
txBuilder.input({
transaction_id: '3677e75c7ba699bfdc6cd57d42f246f86f63aefd76025006ac78313fad2bba21',
transaction_index: 1,
});
const outputAmount = 7823121;
txBuilder.output({
address: testData.rawTx.outputAddress1.address,
amount: outputAmount.toString(),
});
const totalInput = 21032023;
txBuilder.changeAddress(testData.rawTx.outputAddress2.address, totalInput.toString());
txBuilder.ttl(800000000);
const tx = (await txBuilder.build()) as Transaction;
const explained = tx.explainTransaction();
explained.outputs.length.should.equal(2);
const recipientOutput = explained.outputs.find((o) => o.address === testData.rawTx.outputAddress1.address);
const changeOutput = explained.outputs.find((o) => o.address === testData.rawTx.outputAddress2.address);
should.exist(recipientOutput);
should.exist(changeOutput);
should.not.exist(recipientOutput!.change);
changeOutput!.change!.should.be.true();
});

it('should mark the change output with change: true for a byron send tx', async () => {
const txBuilder = factory.getTransferBuilder();
txBuilder.input({
transaction_id: '1b53331e069a6e58fe77919d30c0cf299d13a2f5b3d9970ce473c1a66d71bf03',
transaction_index: 1,
});
const outputAmount = 200000000;
txBuilder.output({
address: testData.rawTxByron.outputAddress1.address,
amount: outputAmount.toString(),
});
const totalInput = 999600000;
txBuilder.changeAddress(testData.rawTxByron.outputAddress2.address, totalInput.toString());
txBuilder.ttl(800000000);
const tx = (await txBuilder.build()) as Transaction;
const explained = tx.explainTransaction();
explained.outputs.length.should.equal(2);
const recipientOutput = explained.outputs.find((o) => o.address === testData.rawTxByron.outputAddress1.address);
const changeOutput = explained.outputs.find((o) => o.address === testData.rawTxByron.outputAddress2.address);
should.exist(recipientOutput);
should.exist(changeOutput);
should.not.exist(recipientOutput!.change);
changeOutput!.change!.should.be.true();
});

it('should not set change on any output when no change address is set (consolidation)', async () => {
const txBuilder = factory.getTransferBuilder();
txBuilder.input({
transaction_id: '3677e75c7ba699bfdc6cd57d42f246f86f63aefd76025006ac78313fad2bba21',
transaction_index: 1,
});
const totalInput = 20000000;
txBuilder.changeAddress(testData.rawTx.outputAddress1.address, totalInput.toString());
txBuilder.ttl(800000000);
const tx = (await txBuilder.build()) as Transaction;
const explained = tx.explainTransaction();
explained.outputs.length.should.equal(1);
explained.outputs[0].change!.should.be.true();
});
});
});
Loading