Skip to content

Commit e1c5a9a

Browse files
committed
test(bitgo): add account-based coin tests for buildParams pass-through
Verify that recipients appears at the top level of /tx/send request body for account-based coins (ETH) alongside halfSigned, confirming WP-8014 is covered by the coin-agnostic WP-8015 changes. Tests cover: - recipients at top level with server buildParams (ETH halfSigned) - recipients at top level via selectParams without server buildParams - nonce and other fields from server buildParams at top level WP-8014 TICKET: WP-8015
1 parent ac58a01 commit e1c5a9a

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

modules/bitgo/test/v2/unit/wallet.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,6 +1957,117 @@ describe('V2 Wallet:', function () {
19571957
});
19581958
});
19591959

1960+
describe('sendMany buildParams pass-through for account-based coins', function () {
1961+
let ethBasecoin;
1962+
let ethWalletForBuildParams: Wallet;
1963+
1964+
before(function () {
1965+
ethBasecoin = bitgo.coin('teth');
1966+
ethWalletForBuildParams = new Wallet(bitgo, ethBasecoin, {
1967+
id: '598f606cd8fc24710d2ebadb1d9459bb',
1968+
coin: 'teth',
1969+
keys: [
1970+
'598f606cd8fc24710d2ebad89dce86c2',
1971+
'598f606cc8e43aef09fcb785221d9dd2',
1972+
'5935d59cf660764331bafcade1855fd7',
1973+
],
1974+
multisigType: 'onchain',
1975+
type: 'hot',
1976+
});
1977+
});
1978+
1979+
it('should include top-level recipients alongside halfSigned in /tx/send for ETH', async function () {
1980+
const recipients = [{ address: '0x5208d8e80c6d1aef9be37b4bd19a9cf75ed93dc8', amount: '200000000000000' }];
1981+
const serverBuildParams = { recipients };
1982+
const prebuildReturn = {
1983+
halfSigned: {
1984+
recipients,
1985+
txHex: '0xdeadbeef',
1986+
expireTime: 1234567890,
1987+
contractSequenceId: 1001,
1988+
},
1989+
buildParams: serverBuildParams,
1990+
};
1991+
sinon.stub(ethWalletForBuildParams, 'prebuildAndSignTransaction').resolves(prebuildReturn);
1992+
sinon.stub(ethBasecoin, 'getExtraPrebuildParams').resolves({});
1993+
1994+
const path = `/api/v2/${ethWalletForBuildParams.coin()}/wallet/${ethWalletForBuildParams.id()}/tx/send`;
1995+
const sendNock = nock(bgUrl)
1996+
.post(path, (body) => {
1997+
// recipients must be at top level (not just inside halfSigned)
1998+
return (
1999+
body.recipients !== undefined &&
2000+
body.recipients[0].address === recipients[0].address &&
2001+
body.halfSigned !== undefined
2002+
);
2003+
})
2004+
.reply(200, { status: 'signed' });
2005+
2006+
const result = await ethWalletForBuildParams.sendMany({ recipients });
2007+
sendNock.isDone().should.be.true();
2008+
result.should.have.property('status', 'signed');
2009+
});
2010+
2011+
it('should include top-level recipients from selectParams even without server buildParams for ETH', async function () {
2012+
const recipients = [{ address: '0x5208d8e80c6d1aef9be37b4bd19a9cf75ed93dc8', amount: '200000000000000' }];
2013+
// No buildParams — simulates old server that doesn't return buildParams
2014+
const prebuildReturn = {
2015+
halfSigned: {
2016+
recipients,
2017+
txHex: '0xdeadbeef',
2018+
expireTime: 1234567890,
2019+
contractSequenceId: 1001,
2020+
},
2021+
};
2022+
sinon.stub(ethWalletForBuildParams, 'prebuildAndSignTransaction').resolves(prebuildReturn);
2023+
sinon.stub(ethBasecoin, 'getExtraPrebuildParams').resolves({});
2024+
2025+
const path = `/api/v2/${ethWalletForBuildParams.coin()}/wallet/${ethWalletForBuildParams.id()}/tx/send`;
2026+
const sendNock = nock(bgUrl)
2027+
.post(path, (body) => {
2028+
// recipients should still be at top level via selectParams (user's original params)
2029+
return (
2030+
body.recipients !== undefined &&
2031+
body.recipients[0].address === recipients[0].address &&
2032+
body.halfSigned !== undefined
2033+
);
2034+
})
2035+
.reply(200, { status: 'signed' });
2036+
2037+
const result = await ethWalletForBuildParams.sendMany({ recipients });
2038+
sendNock.isDone().should.be.true();
2039+
result.should.have.property('status', 'signed');
2040+
});
2041+
2042+
it('should include eip1559 and nonce from server buildParams at top level for ETH', async function () {
2043+
const recipients = [{ address: '0x5208d8e80c6d1aef9be37b4bd19a9cf75ed93dc8', amount: '200000000000000' }];
2044+
const eip1559 = { maxPriorityFeePerGas: '57500000', maxFeePerGas: '510214356' };
2045+
const serverBuildParams = { recipients, nonce: 42, memo: { value: 'test' } };
2046+
const prebuildReturn = {
2047+
halfSigned: {
2048+
recipients,
2049+
txHex: '0xdeadbeef',
2050+
eip1559,
2051+
contractSequenceId: 3371928,
2052+
},
2053+
buildParams: serverBuildParams,
2054+
};
2055+
sinon.stub(ethWalletForBuildParams, 'prebuildAndSignTransaction').resolves(prebuildReturn);
2056+
sinon.stub(ethBasecoin, 'getExtraPrebuildParams').resolves({});
2057+
2058+
const path = `/api/v2/${ethWalletForBuildParams.coin()}/wallet/${ethWalletForBuildParams.id()}/tx/send`;
2059+
const sendNock = nock(bgUrl)
2060+
.post(path, (body) => {
2061+
return body.recipients !== undefined && body.halfSigned !== undefined && body.nonce === 42;
2062+
})
2063+
.reply(200, { status: 'signed' });
2064+
2065+
const result = await ethWalletForBuildParams.sendMany({ recipients });
2066+
sendNock.isDone().should.be.true();
2067+
result.should.have.property('status', 'signed');
2068+
});
2069+
});
2070+
19602071
describe('Maximum Spendable', function maximumSpendable() {
19612072
let bgUrl;
19622073

0 commit comments

Comments
 (0)