Skip to content

Commit 02590c5

Browse files
authored
fix(express): sendMany transfers optional field
2 parents 2bf1328 + 166deae commit 02590c5

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

modules/express/src/typedRoutes/api/v2/sendmany.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@ export const PendingApproval = t.type({
695695
const SendManyResponseBasic = t.type({
696696
/** Transfer details - varies by coin and wallet type */
697697
transfer: optional(Transfer),
698+
/** Array of transfers (includes main transfer + optional fee transfer) */
699+
transfers: optional(t.array(Transfer)),
698700
/** Transaction status (e.g., 'signed', 'accepted', 'pendingApproval') */
699701
status: optional(t.string),
700702
/** Transaction hex */

modules/express/test/unit/typedRoutes/sendmany.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,82 @@ describe('SendMany V2 codec tests', function () {
766766
tokenId: '12345',
767767
});
768768
});
769+
770+
it('should handle response with transfers array (main transfer + fee transfer)', async function () {
771+
const mainTransfer = createMockTransfer({
772+
id: 'transfer-main-123',
773+
type: 'send',
774+
value: 1000000,
775+
valueString: '1000000',
776+
fee: 5000,
777+
feeString: '5000',
778+
});
779+
780+
const feeTransfer = createMockTransfer({
781+
id: 'transfer-fee-456',
782+
type: 'fee',
783+
value: 0,
784+
valueString: '0',
785+
fee: 5000,
786+
feeString: '5000',
787+
});
788+
789+
const mockResponseWithTransfers = {
790+
status: 'signed',
791+
tx: '0100000001c7dad3d9607a23c45a6c1c5ad7bce02acff71a0f21eb4a72a59d0c0e19402d0f0000000000ffffffff0180a21900000000001976a914c918e1b36f2c72b1aaef94dbb7f578a4b68b542788ac00000000',
792+
txid: '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
793+
transfer: mainTransfer,
794+
transfers: [mainTransfer, feeTransfer], // Array with main + fee transfer
795+
};
796+
797+
const requestBody = {
798+
recipients: [
799+
{
800+
address: 'mzKTJw3XJNb7VfkFP77mzPJJz4Dkp4M1T6',
801+
amount: 1000000,
802+
},
803+
],
804+
walletPassphrase: 'test_passphrase_12345',
805+
};
806+
807+
const mockWallet = {
808+
sendMany: sinon.stub().resolves(mockResponseWithTransfers),
809+
_wallet: { multisigType: 'onchain' },
810+
};
811+
812+
const walletsGetStub = sinon.stub().resolves(mockWallet);
813+
const mockCoin = {
814+
wallets: sinon.stub().returns({
815+
get: walletsGetStub,
816+
}),
817+
};
818+
819+
sinon.stub(BitGo.prototype, 'coin').returns(mockCoin as any);
820+
821+
const result = await agent
822+
.post(`/api/v2/${coin}/wallet/${walletId}/sendmany`)
823+
.set('Authorization', 'Bearer test_access_token_12345')
824+
.set('Content-Type', 'application/json')
825+
.send(requestBody);
826+
827+
assert.strictEqual(result.status, 200);
828+
829+
// Verify the response includes transfers array
830+
const decodedResponse = assertDecode(SendManyResponse, result.body);
831+
assertSendManyResponse(decodedResponse);
832+
833+
assert.ok(decodedResponse.transfers, 'Response should include transfers array');
834+
assert.strictEqual(Array.isArray(decodedResponse.transfers), true, 'transfers should be an array');
835+
assert.strictEqual(decodedResponse.transfers.length, 2, 'transfers should contain main + fee transfer');
836+
837+
// Verify main transfer
838+
assert.strictEqual(decodedResponse.transfers[0].id, 'transfer-main-123');
839+
assert.strictEqual(decodedResponse.transfers[0].type, 'send');
840+
841+
// Verify fee transfer
842+
assert.strictEqual(decodedResponse.transfers[1].id, 'transfer-fee-456');
843+
assert.strictEqual(decodedResponse.transfers[1].type, 'fee');
844+
});
769845
});
770846

771847
describe('Request Validation', function () {

0 commit comments

Comments
 (0)