@ledgerhq/hw-app-eth
Version:
Ledger Hardware Wallet Ethereum Application API
843 lines (801 loc) • 88.2 kB
text/typescript
import axios from "axios";
import { fail } from "assert";
import { ethers } from "ethers";
import BigNumber from "bignumber.js";
import { openTransportReplayer, RecordStore } from "@ledgerhq/hw-transport-mocker";
import Eth, { ledgerService } from "../src/Eth";
import CAL_ETH from "./fixtures/SignatureCALEth";
import ERC20_ABI from "./fixtures/ABI/ERC20.json";
import ERC721_ABI from "./fixtures/ABI/ERC721.json";
import ERC1155_ABI from "./fixtures/ABI/ERC1155.json";
import PARASWAP_ABI from "./fixtures/ABI/PARASWAP.json";
import { ResolutionConfig } from "../src/services/types";
import ParaswapJSON from "./fixtures/REST/Paraswap-Plugin.json";
import { byContractAddressAndChainId } from "../src/services/ledger/erc20";
import { ERC1155_CLEAR_SIGNED_SELECTORS, ERC721_CLEAR_SIGNED_SELECTORS } from "../src/utils";
jest.mock("axios");
describe("Eth app biding", () => {
describe("clearSignTransaction", () => {
beforeEach(() => {
jest.resetAllMocks();
});
it("should clear sign the coin transaction", async () => {
const spy = jest.spyOn(axios, "request");
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e00400003f058000002c8000003c80000000000000000000000002e801808417d78400850c529dc58c82520894b0b5b0106d69fe64545a60a68c014f7570d3f8610180c0
<= 00339a8118c0329e403415129205d1d019e5fc5c95bc746b7e9e6efde3ddebfc1107c0393a6bba61a6f3eabc9a1d8298820fd0316436b49b0bc4082bfab81531e39000
`),
);
const eth = new Eth(transport);
const result = await eth.clearSignTransaction(
"44'/60'/0'/0/0",
ethers.utils
.serializeTransaction({
to: "0xB0b5B0106D69fE64545A60A68C014f7570D3F861",
value: ethers.BigNumber.from("1"),
gasLimit: ethers.BigNumber.from("21000"),
maxPriorityFeePerGas: ethers.BigNumber.from("400000000"),
maxFeePerGas: ethers.BigNumber.from("52925678988"),
chainId: 1,
nonce: 0,
type: 2,
})
.substring(2),
{ erc20: true, externalPlugins: true, nft: true },
true,
);
expect(result).toEqual({
r: "339a8118c0329e403415129205d1d019e5fc5c95bc746b7e9e6efde3ddebfc11",
s: "07c0393a6bba61a6f3eabc9a1d8298820fd0316436b49b0bc4082bfab81531e3",
v: "00",
});
expect(spy).not.toHaveBeenCalled();
});
it("should clear sign the ERC20 transaction", async () => {
const spy = jest.spyOn(axios, "get");
spy.mockImplementation(async url => {
if (url?.includes("erc20-signatures")) {
return { data: CAL_ETH } as any;
}
return Promise.reject({ response: { status: 404 } }) as any;
});
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e00a000068054d415449437d1afa7b718fb893db30a3abc0cfc608aacfebb000000012000000013044022000d8fa7b6e409a0dc55723ba975179e7d1181d1fc78fccbece4e5a264814366a02203927d84a710c8892d02f7386ad20147c75fba4bdd486b0256ecd005770a7ca5b
<= 9000
=> e004000085058000002c8000003c80000000000000000000000002f86d01808420c85580850dfe94e19e82fd25947d1afa7b718fb893db30a3abc0cfc608aacfebb080b844a9059cbb000000000000000000000000b0b5b0106d69fe64545a60a68c014f7570d3f8610000000000000000000000000000000000000000000000000de0b6b3a7640000c0
<= 00089a7656b73c72721952d9102dcb608b5f8e9e12e8dfa5d546743e3aa5ff99e24adc7e77795383bb1df13c572db4abfbce86ee4bbe3eaf9b3b50e5b5524793829000
`),
);
const eth = new Eth(transport);
const contract = new ethers.utils.Interface(ERC20_ABI);
const result = await eth.clearSignTransaction(
"44'/60'/0'/0/0",
ethers.utils
.serializeTransaction({
to: "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0",
value: ethers.BigNumber.from("0"),
gasLimit: ethers.BigNumber.from("64805"),
maxPriorityFeePerGas: ethers.BigNumber.from("550000000"),
maxFeePerGas: ethers.BigNumber.from("60105744798"),
data: contract.encodeFunctionData("transfer", [
"0xb0b5b0106d69fe64545a60a68c014f7570d3f861",
ethers.utils.parseUnits("1", 18),
]),
chainId: 1,
nonce: 0,
type: 2,
})
.substring(2),
{ erc20: true, externalPlugins: true, nft: true },
true,
);
expect(result).toEqual({
r: "089a7656b73c72721952d9102dcb608b5f8e9e12e8dfa5d546743e3aa5ff99e2",
s: "4adc7e77795383bb1df13c572db4abfbce86ee4bbe3eaf9b3b50e5b552479382",
v: "00",
});
expect(spy).toHaveBeenCalledTimes(2); // 1 time for ERC20 dynamic CAL + 1 time for Ethereum plugins
});
it("should clear sign the ERC721 transaction with plugin load", async () => {
const contractAddr = "0x60f80121c31a0d46b5279700f9df786054aa5ee5";
const spy = jest.spyOn(axios, "get");
spy.mockImplementation(async url => {
if (
url.includes(
`${contractAddr}/plugin-selector/${ERC721_CLEAR_SIGNED_SELECTORS.SAFE_TRANSFER_FROM}`,
)
) {
return {
data: {
payload:
"01010645524337323160f80121c31a0d46b5279700f9df786054aa5ee542842e0e0000000000000001020147304502203fa78c4aaca8c8e7e69c4a5a360d91f35d577827b0da2f3fb4adf16a0f94601802210089031d0b8ac2e66a66fc9062b65a233772df46de01f5f28b0c631a4700c1562f",
},
};
} else if (url.includes(`contracts/${contractAddr}`)) {
return {
data: {
payload:
"01010752617269626c6560f80121c31a0d46b5279700f9df786054aa5ee500000000000000010101473045022067d4254b89367a7e35fe7507001d6c8a0844a35aa4839c94a4724de1f332382d022100b9353df1f6f69feb9970946603723657f5682e0cac1b480a2beb2ecba10c872f",
},
} as any;
}
return Promise.reject({ response: { status: 404 } }) as any;
});
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e01600007301010645524337323160f80121c31a0d46b5279700f9df786054aa5ee542842e0e0000000000000001020147304502203fa78c4aaca8c8e7e69c4a5a360d91f35d577827b0da2f3fb4adf16a0f94601802210089031d0b8ac2e66a66fc9062b65a233772df46de01f5f28b0c631a4700c1562f
<= 9000
=> e01400007001010752617269626c6560f80121c31a0d46b5279700f9df786054aa5ee500000000000000010101473045022067d4254b89367a7e35fe7507001d6c8a0844a35aa4839c94a4724de1f332382d022100b9353df1f6f69feb9970946603723657f5682e0cac1b480a2beb2ecba10c872f
<= 9000
=> e004000096058000002c8000003c80000000000000000000000002f88e018084448b9b80851278cdd392830238699460f80121c31a0d46b5279700f9df786054aa5ee580b86442842e0e0000000000000000000000006cbcd73cd8e8a42844662f0a0e76d7f79afd933d000000000000000000000000b0b5b0106d69fe64545a60a68c014f7570d3f8610000000000000000000000000000000000
<= 9000
=> e004800010000000000000000000000000112999c0
<= 0187ce0994bbdfdfd93990a5afc03d7cf70a14c9efaabac810724a41f6375f54236c0056a02dc07650b1e68f86b9f18a92ff689a9eddf710bd9f76739260fff1939000
`),
);
const eth = new Eth(transport);
const contract = new ethers.utils.Interface(ERC721_ABI);
const result = await eth.clearSignTransaction(
"44'/60'/0'/0/0",
ethers.utils
.serializeTransaction({
to: contractAddr,
value: ethers.BigNumber.from("0"),
gasLimit: ethers.BigNumber.from("145513"),
maxPriorityFeePerGas: ethers.BigNumber.from("1150000000"),
maxFeePerGas: ethers.BigNumber.from("79336166290"),
data: contract.encodeFunctionData(
contract.getFunction("safeTransferFrom(address,address,uint256)"),
[
"0x6cBCD73CD8e8a42844662f0A0e76D7F79Afd933d",
"0xb0b5b0106d69fe64545a60a68c014f7570d3f861",
"1124761",
],
),
chainId: 1,
nonce: 0,
type: 2,
})
.substring(2),
{ erc20: true, externalPlugins: true, nft: true },
true,
);
expect(result).toEqual({
r: "87ce0994bbdfdfd93990a5afc03d7cf70a14c9efaabac810724a41f6375f5423",
s: "6c0056a02dc07650b1e68f86b9f18a92ff689a9eddf710bd9f76739260fff193",
v: "01",
});
expect(spy).toHaveBeenCalledTimes(3); // 1 time backend nft selector + 1 time backend nft information + plugin json file
});
it("should clear sign the ERC1155 transaction with plugin load", async () => {
const contractAddr = "0xd07dc4262bcdbf85190c01c996b4c06a461d2430";
const spy = jest.spyOn(axios, "get");
spy.mockImplementation(async url => {
if (
url.includes(
`${contractAddr}/plugin-selector/${ERC1155_CLEAR_SIGNED_SELECTORS.SAFE_TRANSFER_FROM}`,
)
) {
return {
data: {
payload:
"01010745524331313535d07dc4262bcdbf85190c01c996b4c06a461d2430f242432a0000000000000001020146304402201b82317133172618ff680589dc38ea3647d59c49a3ee299c09180e865f6786890220027a7ad14fc8beaa14b7e7c907e26abb2f0aad6ccd93b245acee7d70517ea062",
},
};
} else if (url.includes(`contracts/${contractAddr}`)) {
return {
data: {
payload:
"01010752617269626c65d07dc4262bcdbf85190c01c996b4c06a461d243000000000000000010101473045022100fddd2264ca0eb3cc8a588d82b41edf9d262145a0ca1f08caab5bb6a4eac34a9e0220602b57cabdc40bbeb3a46a5d362ac2544124c9806aee196a87a51f61bb7e9230",
},
} as any;
}
return Promise.reject({ response: { status: 404 } }) as any;
});
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e01600007301010745524331313535d07dc4262bcdbf85190c01c996b4c06a461d2430f242432a0000000000000001020146304402201b82317133172618ff680589dc38ea3647d59c49a3ee299c09180e865f6786890220027a7ad14fc8beaa14b7e7c907e26abb2f0aad6ccd93b245acee7d70517ea062
<= 9000
=> e01400007001010752617269626c65d07dc4262bcdbf85190c01c996b4c06a461d243000000000000000010101473045022100fddd2264ca0eb3cc8a588d82b41edf9d262145a0ca1f08caab5bb6a4eac34a9e0220602b57cabdc40bbeb3a46a5d362ac2544124c9806aee196a87a51f61bb7e9230
<= 9000
=> e004000096058000002c8000003c80000000000000000000000002f8ee01808414dc9380850d54eb0ea883010ab494d07dc4262bcdbf85190c01c996b4c06a461d243080b8c4f242432a0000000000000000000000006cbcd73cd8e8a42844662f0a0e76d7f79afd933d000000000000000000000000b0b5b0106d69fe64545a60a68c014f7570d3f8610000000000000000000000000000000000
<= 9000
=> e00480007000000000000000000000000004041c000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000c0
<= 016467047c39c2c3db9dbe8aa03802c80830beb659f0eed7470735098f2c44cfae7b2aa36e2f31c6e0d37a00b93789ef4eef4fd016dd3b92fa893e7e741a152be99000
`),
);
const eth = new Eth(transport);
const contract = new ethers.utils.Interface(ERC1155_ABI);
const result = await eth.clearSignTransaction(
"44'/60'/0'/0/0",
ethers.utils
.serializeTransaction({
to: contractAddr,
value: ethers.BigNumber.from("0"),
gasLimit: ethers.BigNumber.from("68276"),
maxPriorityFeePerGas: ethers.BigNumber.from("350000000"),
maxFeePerGas: ethers.BigNumber.from("57259265704"),
data: contract.encodeFunctionData("safeTransferFrom", [
"0x6cBCD73CD8e8a42844662f0A0e76D7F79Afd933d",
"0xb0b5b0106d69fe64545a60a68c014f7570d3f861",
"263196",
"1",
"0x",
]),
chainId: 1,
nonce: 0,
type: 2,
})
.substring(2),
{ erc20: true, externalPlugins: true, nft: true },
true,
);
expect(result).toEqual({
r: "6467047c39c2c3db9dbe8aa03802c80830beb659f0eed7470735098f2c44cfae",
s: "7b2aa36e2f31c6e0d37a00b93789ef4eef4fd016dd3b92fa893e7e741a152be9",
v: "01",
});
expect(spy).toHaveBeenCalledTimes(3); // 1 time backend nft selector + 1 time backend nft information + plugin json file
});
it("should clear sign the external plugin transaction", async () => {
const spy = jest.spyOn(axios, "get");
spy.mockImplementation(async url => {
if (url?.includes("erc20-signatures")) {
return { data: CAL_ETH } as any;
} else if (url?.includes("ethereum.json")) {
return { data: ParaswapJSON } as any;
}
return Promise.reject({ response: { status: 404 } }) as any;
});
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e012000068085061726173776170def171fe48cf0115b1d80b88dc8eab59176fee5754e3f31b3045022100ec8e69d23371437ce5b5f1d894b836c036748e2fabf52fb069c34a9d0ba8704a022013e761d81c26ece4cb0ea385813699b7e646354d3404ed55f4bf068db02dda9a
<= 9000
=> e00a000068054d415449437d1afa7b718fb893db30a3abc0cfc608aacfebb000000012000000013044022000d8fa7b6e409a0dc55723ba975179e7d1181d1fc78fccbece4e5a264814366a02203927d84a710c8892d02f7386ad20147c75fba4bdd486b0256ecd005770a7ca5b
<= 9000
=> e00a000067034441496b175474e89094c44da98b954eedeac495271d0f00000012000000013045022100b3aa979633284eb0f55459099333ab92cf06fdd58dc90e9c070000c8e968864c02207b10ec7d6609f51dda53d083a6e165a0abf3a77e13250e6f260772809b49aff5
<= 9000
=> e004000096058000002c8000003c80000000000000000000000002f9048f018084448b9b8085143fc44a5883048f8b94def171fe48cf0115b1d80b88dc8eab59176fee5780b9046454e3f31b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000007d1afa7b718fb893db30a3abc0cfc608aacfebb00000000000000000000000006b1754
<= 9000
=> e00480009674e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000014655db2d8c71619000000000000000000000000000000000000000000000000147f9aa1bc47718c00000000000000000000000000000000000000000000000000000000000001e00000000000
<= 9000
=> e004800096000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000558247e365be655f9144e1a0140d79
<= 9000
=> e0048000963984372ef3010000000000000000000000000000000000000000000000000000000000405f000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000640be3823d2fae4b5ec240cd871aa6b675e99899000000000000000000000000000000000000000000000000000000000000000000
<= 9000
=> e004800096000000000000000000000000000001000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000000000000000000000000000000000000000000124c04b8d59000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a0000000
<= 9000
=> e004800096000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee5700000000000000000000000000000000000000000000000000000000640b9d320000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000
<= 9000
=> e0048000960000000000002b7d1afa7b718fb893db30a3abc0cfc608aacfebb00027106b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000
<= 9000
=> e00480008e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0
<= 00775aed341ee9f0a0d0c0d724e242f9def19c09df02d1c474bc5750c86b952f5535bd98bc4a6482a895e94cd5ca9351ec1daeb955251a35dc8c2fb86851bf49189000
`),
);
const eth = new Eth(transport);
const contract = new ethers.utils.Interface(PARASWAP_ABI);
const result = await eth.clearSignTransaction(
"44'/60'/0'/0/0",
ethers.utils
.serializeTransaction({
to: "0xdef171fe48cf0115b1d80b88dc8eab59176fee57",
value: ethers.BigNumber.from("0"),
gasLimit: ethers.BigNumber.from("298891"),
maxPriorityFeePerGas: ethers.BigNumber.from("1150000000"),
maxFeePerGas: ethers.BigNumber.from("86969174616"),
data: contract.encodeFunctionData("simpleSwap", [
[
"0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", // MATIC
"0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI
"0x0de0b6b3a7640000", // 1 MATIC
"0x14655db2d8c71619", // ~1.469 DAI
"0x147f9aa1bc47718c", // EXPECT 1.477 DAI
["0xE592427A0AEce92De3Edee1F18E0157C05861564"],
"0xc04b8d59000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee5700000000000000000000000000000000000000000000000000000000640b9d320000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002b7d1afa7b718fb893db30a3abc0cfc608aacfebb00027106b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000",
["0x00", "0x0124"],
["0x00"],
"0x0000000000000000000000000000000000000000",
"0x558247e365be655f9144e1a0140D793984372Ef3",
"0x010000000000000000000000000000000000000000000000000000000000405f",
"0x",
"0x640be382",
"0x3d2fae4b5ec240cd871aa6b675e99899",
],
]),
chainId: 1,
nonce: 0,
type: 2,
})
.substring(2),
{ erc20: true, externalPlugins: true, nft: true },
true,
);
expect(result).toEqual({
r: "775aed341ee9f0a0d0c0d724e242f9def19c09df02d1c474bc5750c86b952f55",
s: "35bd98bc4a6482a895e94cd5ca9351ec1daeb955251a35dc8c2fb86851bf4918",
v: "00",
});
expect(spy).toHaveBeenCalledTimes(3); // 1 time plugin json file + 2 times CAL signatures <-- FIXME 1 time should be enough
});
it("should throw in case of error with strict mode", async () => {
const err = new Error("strictModeCatchThis");
jest.spyOn(ledgerService, "resolveTransaction").mockRejectedValue(err);
const transport = await openTransportReplayer(RecordStore.fromString(""));
const eth = new Eth(transport);
try {
await eth.clearSignTransaction(
"44'/60'/0'/0/0",
ethers.utils
.serializeTransaction({
to: "0xB0b5B0106D69fE64545A60A68C014f7570D3F861",
value: ethers.BigNumber.from("1"),
gasLimit: ethers.BigNumber.from("21000"),
maxPriorityFeePerGas: ethers.BigNumber.from("400000000"),
maxFeePerGas: ethers.BigNumber.from("52925678988"),
chainId: 1,
nonce: 0,
type: 2,
})
.substring(2),
{ erc20: true, externalPlugins: true, nft: true },
true,
);
fail("Promise should have been rejected");
} catch (e) {
expect(e).toBe(err);
} finally {
// @ts-expect-error jest mock
ledgerService.resolveTransaction.mockRestore();
}
});
it("should not throw in case of error without strict mode", async () => {
const err = new Error("strictModeCatchThis");
jest.spyOn(ledgerService, "resolveTransaction").mockRejectedValue(err);
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e00400003f058000002c8000003c80000000000000000000000002e801808417d78400850c529dc58c82520894b0b5b0106d69fe64545a60a68c014f7570d3f8610180c0
<= 00339a8118c0329e403415129205d1d019e5fc5c95bc746b7e9e6efde3ddebfc1107c0393a6bba61a6f3eabc9a1d8298820fd0316436b49b0bc4082bfab81531e39000
`),
);
const eth = new Eth(transport);
try {
await eth.clearSignTransaction(
"44'/60'/0'/0/0",
ethers.utils
.serializeTransaction({
to: "0xB0b5B0106D69fE64545A60A68C014f7570D3F861",
value: ethers.BigNumber.from("1"),
gasLimit: ethers.BigNumber.from("21000"),
maxPriorityFeePerGas: ethers.BigNumber.from("400000000"),
maxFeePerGas: ethers.BigNumber.from("52925678988"),
chainId: 1,
nonce: 0,
type: 2,
})
.substring(2),
{ erc20: true, externalPlugins: true, nft: true },
false,
);
} catch (e) {
fail("Should not throw");
} finally {
// @ts-expect-error jest mock
ledgerService.resolveTransaction.mockRestore();
}
});
});
describe("hw-app-eth older Integration Tests", () => {
beforeEach(() => {
jest.resetAllMocks();
});
async function signTxWithResolution(
eth: Eth,
path: string,
tx: string,
resolutionConfig?: ResolutionConfig,
) {
const resolution = await ledgerService
.resolveTransaction(
tx,
{},
resolutionConfig || { externalPlugins: true, erc20: true, nft: true },
)
.catch(e => {
console.warn(
"an error occurred in resolveTransaction => fallback to blind signing: " + String(e),
);
return null;
});
return eth.signTransaction(path, tx, resolution);
}
test("getAppConfiguration", async () => {
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e006000000
<= 010101069000
`),
);
const eth = new Eth(transport);
const result = await eth.getAppConfiguration();
expect(result).toEqual({
arbitraryDataEnabled: 1,
erc20ProvisioningNecessary: 0,
starkEnabled: 0,
starkv2Supported: 0,
version: "1.1.6",
});
});
test("getAddress", async () => {
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e002000015058000002c8000003c800000008000000000000000
<= 4104df00ad3869baad7ce54f4d560ba7f268d542df8f2679a5898d78a690c3db8f9833d2973671cb14b088e91bdf7c0ab00029a576473c0e12f84d252e630bb3809b28436241393833363265313939633431453138363444303932334146393634366433413634383435319000
`),
);
const eth = new Eth(transport);
const result = await eth.getAddress("44'/60'/0'/0'/0");
expect(result).toEqual({
address: "0xCbA98362e199c41E1864D0923AF9646d3A648451",
publicKey:
"04df00ad3869baad7ce54f4d560ba7f268d542df8f2679a5898d78a690c3db8f9833d2973671cb14b088e91bdf7c0ab00029a576473c0e12f84d252e630bb3809b",
});
});
test("getAddress with chain ID", async () => {
const transportHolesky = await openTransportReplayer(
RecordStore.fromString(`
=> e00201001d058000002c8000003c8000000000000000000000000000000000004268
<= 41047d8d3c470d1cfd8525d9537efdb92319a13a9bc9e336b6621fa5a664d2591b60fcd4f7882b0ff07d5ea0697050c7d23428daa5beaf6268cbac1369c278c6d8ea28366342434437334344386538613432383434363632663041306537364437463739416664393333649000
`),
);
const ethHolesky = new Eth(transportHolesky);
const resultHolesky = await ethHolesky.getAddress("44'/60'/0'/0/0", true, false, "17000");
expect(resultHolesky).toEqual({
address: "0x6cBCD73CD8e8a42844662f0A0e76D7F79Afd933d",
publicKey:
"047d8d3c470d1cfd8525d9537efdb92319a13a9bc9e336b6621fa5a664d2591b60fcd4f7882b0ff07d5ea0697050c7d23428daa5beaf6268cbac1369c278c6d8ea",
});
const transportPolygon = await openTransportReplayer(
RecordStore.fromString(`
=> e00201001d058000002c8000003c8000000000000000000000000000000000000089
<= 41047d8d3c470d1cfd8525d9537efdb92319a13a9bc9e336b6621fa5a664d2591b60fcd4f7882b0ff07d5ea0697050c7d23428daa5beaf6268cbac1369c278c6d8ea28366342434437334344386538613432383434363632663041306537364437463739416664393333649000
`),
);
const ethPolygon = new Eth(transportPolygon);
const resultPolygon = await ethPolygon.getAddress("44'/60'/0'/0/0", true, false, "137");
expect(resultPolygon).toEqual({
address: "0x6cBCD73CD8e8a42844662f0A0e76D7F79Afd933d",
publicKey:
"047d8d3c470d1cfd8525d9537efdb92319a13a9bc9e336b6621fa5a664d2591b60fcd4f7882b0ff07d5ea0697050c7d23428daa5beaf6268cbac1369c278c6d8ea",
});
const transportGoerli = await openTransportReplayer(
RecordStore.fromString(`
=> e00201001d058000002c8000003c8000000000000000000000000000000000000005
<= 41047d8d3c470d1cfd8525d9537efdb92319a13a9bc9e336b6621fa5a664d2591b60fcd4f7882b0ff07d5ea0697050c7d23428daa5beaf6268cbac1369c278c6d8ea28366342434437334344386538613432383434363632663041306537364437463739416664393333649000
`),
);
const ethGoerli = new Eth(transportGoerli);
const resultGoerli = await ethGoerli.getAddress("44'/60'/0'/0/0", true, false, "5");
expect(resultGoerli).toEqual({
address: "0x6cBCD73CD8e8a42844662f0A0e76D7F79Afd933d",
publicKey:
"047d8d3c470d1cfd8525d9537efdb92319a13a9bc9e336b6621fa5a664d2591b60fcd4f7882b0ff07d5ea0697050c7d23428daa5beaf6268cbac1369c278c6d8ea",
});
});
test("signTransaction", async () => {
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e00400003e058000002c8000003c800000008000000000000000e8018504e3b292008252089428ee52a8f3d6e5d15f8b131996950d7f296c7952872bd72a2487400080
<= 1b3694583045a85ada8d15d5e01b373b00e86a405c9c52f7835691dcc522b7353b30392e638a591c65ed307809825ca48346980f52d004ab7a5f93657f7e62a4009000
`),
);
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0'/0",
"e8018504e3b292008252089428ee52a8f3d6e5d15f8b131996950d7f296c7952872bd72a2487400080",
);
expect(result).toEqual({
r: "3694583045a85ada8d15d5e01b373b00e86a405c9c52f7835691dcc522b7353b",
s: "30392e638a591c65ed307809825ca48346980f52d004ab7a5f93657f7e62a400",
v: "1b",
});
});
test("signTransaction supports EIP1559", async () => {
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e004000046058000002c8000003c80000000000000000000000002ef0306843b9aca008504a817c80082520894b2bb2b958afa2e96dab3f3ce7162b87daea39017872386f26fc1000080c0
<= 003ccff815955e82c416dcf2ace0bf0aa5f479acd47f5152f0c1753cf68fb723746774b8bff4f776f2788bb19c87c22ca8a2933ea4415eed8d25a9ea0500c81ce19000
`),
);
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0/0",
"02ef0306843b9aca008504a817c80082520894b2bb2b958afa2e96dab3f3ce7162b87daea39017872386f26fc1000080c0",
);
expect(result).toEqual({
r: "3ccff815955e82c416dcf2ace0bf0aa5f479acd47f5152f0c1753cf68fb72374",
s: "6774b8bff4f776f2788bb19c87c22ca8a2933ea4415eed8d25a9ea0500c81ce1",
v: "00",
});
});
test("signTransaction supports EIP1559 with tokens", async () => {
jest.spyOn(axios, "get").mockResolvedValue(undefined);
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e00a000066035a5258e41d2489571d322189246dafa5ebde1f4699f4980000001200000001304402200ae8634c22762a8ba41d2acb1e068dcce947337c6dd984f13b820d396176952302203306a49d8a6c35b11a61088e1570b3928ca3a0db6bd36f577b5ef87628561ff7
<= 9000
=> e00400008c058000002c8000003c80000000000000000000000002f8740106843b9aca008504a817c80082520894e41d2489571d322189246dafa5ebde1f4699f498872386f26fc10000b844095ea7b3000000000000000000000000221657776846890989a759ba2973e427dff5c9bb0000000000000000000000000000000000000000000000004563918244f40000c0
<= 00d6814aa5db69de910824b14462af006fde864224c616ab93e30f646e7309a93f0312ac6e580e918ce6e39e5f910cb95ba7b68167f4d71e581dec2495a198ecc09000
`),
);
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0/0",
"02f8740106843b9aca008504a817c80082520894e41d2489571d322189246dafa5ebde1f4699f498872386f26fc10000b844095ea7b3000000000000000000000000221657776846890989a759ba2973e427dff5c9bb0000000000000000000000000000000000000000000000004563918244f40000c0",
);
expect(result).toEqual({
r: "d6814aa5db69de910824b14462af006fde864224c616ab93e30f646e7309a93f",
s: "0312ac6e580e918ce6e39e5f910cb95ba7b68167f4d71e581dec2495a198ecc0",
v: "00",
});
});
test("signTransaction supports EIP2930", async () => {
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e004000096058000002c8000003c80000000000000000000000001f886030685012a05f20082520894b2bb2b958afa2e96dab3f3ce7162b87daea39017872386f26fc1000080f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000
<= 9000
=> e0048000080000000000000007
<= 01a74d82400f49d1f9d85f734c22a1648d4ab74bb6367bef54c6abb0936be3d8b77a84a09673394c3c1bd76be05620ee17a2d0ff32837607625efa433cc017854e9000
`),
);
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0/0",
"01f886030685012a05f20082520894b2bb2b958afa2e96dab3f3ce7162b87daea39017872386f26fc1000080f85bf85994de0b295669a9fd93d5f28d9ec85e40f4cb697baef842a00000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000007",
);
expect(result).toEqual({
r: "a74d82400f49d1f9d85f734c22a1648d4ab74bb6367bef54c6abb0936be3d8b7",
s: "7a84a09673394c3c1bd76be05620ee17a2d0ff32837607625efa433cc017854e",
v: "01",
});
});
const paraswapAPDUs =
`=> e0120000670850617261737761701bd435f3c054b6e901b7b108a0ab7617c808677bcfc0afeb304402201c0cbe69aac517825b3a6eb5e7251e8fd57ff93a43bd3df52c7a841818eda81b022001a10cc326efaee2463fc96e7c29739c308fb8179bd2ac37303662bae4f7705c
<= 9000
=> e00a0000680531494e4348111111111117dc0aa78b770fa6a738034120c3020000001200000001304402204623e5f1375c54a446157ae8a739204284cf053634b7abd083dc5f5d2675c4e702206ff94b4c84ba9e93f44065c38d7c92506621fa69ba04f767aa58221de8afbf17
<= 9000
=> e004000096058000002c8000003c800000000000000000000000f903cd82043d8509c765240083042e73941bd435f3c054b6e901b7b108a0ab7617c808677b80b903a4cfc0afeb000000000000000000000000111111111117dc0aa78b770fa6a738034120c302000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000
<= 9000
=> e0048000960000000af10f7eb24f506cfd00000000000000000000000000000000000000000000000002a5b905b3c9fa4c00000000000000000000000000000000000000000000000002baaee8d905020a000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c000000000000000000000
<= 9000
=> e004800096000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000000
<= 9000
=> e004800096000000000000000000000000000000000000000000000000000000000000000100000000000000000000000086d3579b043585a97532514016dcf0c2d6c4b6a100000000000000000000000000000000000000000000000000000000000000c499585aac00000000000000000000000000000000000000000000000af10f7eb24f506cfd000000000000000000000000000000000000
<= 9000
=> e004800096000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000111111111117dc0aa78b770fa6a738034120c302000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000
<= 9000
=> e00480009600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000010000
<= 9000
=> e00480006100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076c65646765723200000000000000000000000000000000000000000000000000018080
<= 26d9e62b0b6ae0c18d3d2ecdf20ce7f1c959e0f609b4e73e2d138bbdc3e1e9390012469e2124a8955b5159f670b0333b803a70dd7dc51558a8f7460b27eed77be59000`.toLowerCase();
test("paraswap", async () => {
jest.spyOn(axios, "get").mockImplementation(async uri => {
if (uri?.includes("plugins/ethereum.json")) {
return {
data: ParaswapJSON,
};
}
return null;
});
const transport = await openTransportReplayer(RecordStore.fromString(paraswapAPDUs));
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0/0",
"f903cd82043d8509c765240083042e73941bd435f3c054b6e901b7b108a0ab7617c808677b80b903a4cfc0afeb000000000000000000000000111111111117dc0aa78b770fa6a738034120c302000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000af10f7eb24f506cfd00000000000000000000000000000000000000000000000002a5b905b3c9fa4c00000000000000000000000000000000000000000000000002baaee8d905020a000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000086d3579b043585a97532514016dcf0c2d6c4b6a100000000000000000000000000000000000000000000000000000000000000c499585aac00000000000000000000000000000000000000000000000af10f7eb24f506cfd000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000111111111117dc0aa78b770fa6a738034120c302000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076c65646765723200000000000000000000000000000000000000000000000000018080",
);
expect(result).toEqual({
r: "d9e62b0b6ae0c18d3d2ecdf20ce7f1c959e0f609b4e73e2d138bbdc3e1e93900",
s: "12469e2124a8955b5159f670b0333b803a70dd7dc51558a8f7460b27eed77be5",
v: "26",
});
});
test("paraswap without plugins CDN but with explicit plugin", async () => {
jest.spyOn(axios, "get").mockImplementation(async uri => {
if (uri?.includes("plugins/ethereum.json")) {
return { data: ParaswapJSON };
}
return null;
});
const transport = await openTransportReplayer(
// behave like paraswap test
RecordStore.fromString(paraswapAPDUs),
);
const eth = new Eth(transport);
eth.setLoadConfig({
pluginBaseURL: null,
extraPlugins: ParaswapJSON,
});
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0/0",
"f903cd82043d8509c765240083042e73941bd435f3c054b6e901b7b108a0ab7617c808677b80b903a4cfc0afeb000000000000000000000000111111111117dc0aa78b770fa6a738034120c302000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000af10f7eb24f506cfd00000000000000000000000000000000000000000000000002a5b905b3c9fa4c00000000000000000000000000000000000000000000000002baaee8d905020a000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000086d3579b043585a97532514016dcf0c2d6c4b6a100000000000000000000000000000000000000000000000000000000000000c499585aac00000000000000000000000000000000000000000000000af10f7eb24f506cfd000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000111111111117dc0aa78b770fa6a738034120c302000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076c65646765723200000000000000000000000000000000000000000000000000018080",
);
expect(result).toEqual({
r: "d9e62b0b6ae0c18d3d2ecdf20ce7f1c959e0f609b4e73e2d138bbdc3e1e93900",
s: "12469e2124a8955b5159f670b0333b803a70dd7dc51558a8f7460b27eed77be5",
v: "26",
});
});
test("signTransactionLargeChainID", async () => {
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e004000043058000002c8000003c800000008000000000000000ed018504e3b292008252089428ee52a8f3d6e5d15f8b131996950d7f296c7952872bd72a248740008082aa008080
<= 1b3694583045a85ada8d15d5e01b373b00e86a405c9c52f7835691dcc522b7353b30392e638a591c65ed307809825ca48346980f52d004ab7a5f93657f7e62a4009000
`),
);
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0'/0",
"ed018504e3b292008252089428ee52a8f3d6e5d15f8b131996950d7f296c7952872bd72a248740008082aa008080",
);
expect(result).toEqual({
r: "3694583045a85ada8d15d5e01b373b00e86a405c9c52f7835691dcc522b7353b",
s: "30392e638a591c65ed307809825ca48346980f52d004ab7a5f93657f7e62a400",
v: "01542b",
});
});
test("signTransactionLargeChainID2", async () => {
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e004000043058000002c8000003c800000008000000000000000ed018504e3b292008252089428ee52a8f3d6e5d15f8b131996950d7f296c7952872bd72a248740008081fa008080
<= 173694583045a85ada8d15d5e01b373b00e86a405c9c52f7835691dcc522b7353b30392e638a591c65ed307809825ca48346980f52d004ab7a5f93657f7e62a4009000
`),
);
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0'/0",
"ed018504e3b292008252089428ee52a8f3d6e5d15f8b131996950d7f296c7952872bd72a248740008081fa008080",
);
expect(result).toEqual({
r: "3694583045a85ada8d15d5e01b373b00e86a405c9c52f7835691dcc522b7353b",
s: "30392e638a591c65ed307809825ca48346980f52d004ab7a5f93657f7e62a400",
v: "0217",
});
});
test("signTransaction5BytesChainID", async () => {
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e00400004c058000002c8000003c800000008000000000000000f8358332d79f85072e9ad0f0830186a094810a9082d51802b2281d23e43e77dd846e51b8ee880194be7d2ebf07b3808502a15c308d8080
<= 84d86809a5e283da8b967c38a1a6351f8c2bde177858449c26348f8d9ce876681672b0ae2862a68f35edc7a5b84d4a39299b98a4973452acf2c6571e9d4cf702d39000
`),
);
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0'/0",
"f8358332d79f85072e9ad0f0830186a094810a9082d51802b2281d23e43e77dd846e51b8ee880194be7d2ebf07b3808502a15c308d8080",
);
expect(result).toEqual({
r: "d86809a5e283da8b967c38a1a6351f8c2bde177858449c26348f8d9ce8766816",
s: "72b0ae2862a68f35edc7a5b84d4a39299b98a4973452acf2c6571e9d4cf702d3",
v: "0542b8613e",
});
});
test("signTransactionChunkedLimit", async () => {
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e004000096058000002c8000003c800000000000000000000000f901ad8205448505c205da808310c8e19402b3f51ac9202aa19be63d61a8c681579d6e3a5180b90184293491160000000000000000000000000000000000000000000000000000000005ee832e0000000000000000000000000000000000000000000000000000000005eeb9ac0000000000000000000000000000000000000000
<= 9000
=> e00480009600000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000505846a0a89dd26fa5cd0677fd5406039c218620000000000000000000000000000000000000000000000000000000001f969fc88a4d19062c1525d6ca664dee285aa573c06e0f8bdd4971032d2b63be6183d05300000000000000000000
<= 9000
=> e004800099000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000041c4c3f1f8711741f2180d850a09a2933bb21dff1c79caf8c45ecda957836ec7e60d78661c28ad96713e5f22a458376422599bd3776d9aeafc02e319ed0c1b41e51c00000000000000000000000000000000000000000000000000000000000000018080
<= 1bdc6ad1d9d847defdffde2f3b70004c89a1a8a6c614fec484891ae8f1ebc46f9966159ca542f5cf36d64278218bfcce24ba96d7495dec25b10a7609346ca063ec9000
`), // Incorrect signature but it doesn't matter for tests
);
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0/0",
"f901ad8205448505c205da808310c8e19402b3f51ac9202aa19be63d61a8c681579d6e3a5180b90184293491160000000000000000000000000000000000000000000000000000000005ee832e0000000000000000000000000000000000000000000000000000000005eeb9ac000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000505846a0a89dd26fa5cd0677fd5406039c218620000000000000000000000000000000000000000000000000000000001f969fc88a4d19062c1525d6ca664dee285aa573c06e0f8bdd4971032d2b63be6183d05300000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000041c4c3f1f8711741f2180d850a09a2933bb21dff1c79caf8c45ecda957836ec7e60d78661c28ad96713e5f22a458376422599bd3776d9aeafc02e319ed0c1b41e51c00000000000000000000000000000000000000000000000000000000000000018080",
);
expect(result).toEqual({
r: "dc6ad1d9d847defdffde2f3b70004c89a1a8a6c614fec484891ae8f1ebc46f99",
s: "66159ca542f5cf36d64278218bfcce24ba96d7495dec25b10a7609346ca063ec",
v: "1b",
});
});
test("signTransactionChunkedLimitBigVRS", async () => {
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e004000096058000002c8000003c800000000000000000000000f9011782abcd8609184e72a00082271094aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa820300b8edbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
<= 9000
=> e004800099bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb258080
<= 1bdc6ad1d9d847defdffde2f3b70004c89a1a8a6c614fec484891ae8f1ebc46f9966159ca542f5cf36d64278218bfcce24ba96d7495dec25b10a7609346ca063ec9000
`),
);
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0/0",
"f9011782abcd8609184e72a00082271094aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa820300b8edbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb258080",
);
expect(result).toEqual({
r: "dc6ad1d9d847defdffde2f3b70004c89a1a8a6c614fec484891ae8f1ebc46f99",
s: "66159ca542f5cf36d64278218bfcce24ba96d7495dec25b10a7609346ca063ec",
v: "1b",
});
});
test("signTransaction coin with domain", async () => {
jest.spyOn(axios, "request").mockImplementationOnce(async ({ url }) => {
if (url?.includes("dev.0xkvn.eth?challenge=0x10126b3d")) {
return {
data: {
payload:
"010103020101130103140101120410126b3d21013c200d6465762e30786b766e2e65746822146cbcd73cd8e8a42844662f0a0e76d7f79afd933d15483046022100c8046e9e13a3cb682db70ec5082d9ea9600070ad747433d1088d02102484d1fa022100d77a34953dd7a86d688a9b90f099643b88b18e922b026f7e4fd8db9ab8121a8b",
},
};
}
});
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e020000000
<= 10126b3d9000
=> e0220100860084010103020101130103140101120410126b3d21013c200d6465762e30786b766e2e65746822146cbcd73cd8e8a42844662f0a0e76d7f79afd933d15483046022100c8046e9e13a3cb682db70ec5082d9ea9600070ad747433d1088d02102484d1fa022100d77a34953dd7a86d688a9b90f099643b88b18e922b026f7e4fd8db9ab8121a8b
<= 9000
=> e004000047058000002c8000003c80000000000000000000000002f001468417d784008509051957f0825208946cbcd73cd8e8a42844662f0a0e76d7f79afd933d8801667275be10d51880c0
<= 00cc0e89a27605a67b3bcb72512c6a48f2b65c7721f9a0dc2591a2a773e1a6d37a149b7a9dce84b9b457300b1b15d1eaa09858e70b6979031cf489c6c0c4507eb29000
`),
);
const eth = new Eth(transport);
const result = await signTxWithResolution(
eth,
"44'/60'/0'/0/0",
"02f001468417d784008509051957f0825208946cbcd73cd8e8a42844662f0a0e76d7f79afd933d8801667275be10d51880c0",
{
erc20: true,
nft: true,
externalPlugins: true,
domains: [
{
registry: "ens",
address: "0x6cBCD73CD8e8a42844662f0A0e76D7F79Afd933d",
domain: "dev.0xkvn.eth",
type: "forward",
},
],
},
);
expect(result).toEqual({
r: "cc0e89a27605a67b3bcb72512c6a48f2b65c7721f9a0dc2591a2a773e1a6d37a",
s: "149b7a9dce84b9b457300b1b15d1eaa09858e70b6979031cf489c6c0c4507eb2",
v: "00",
});
});
test("signTransaction erc20 with domain", async () => {
jest.spyOn(axios, "get").mockResolvedValue(null);
jest.spyOn(axios, "request").mockImplementationOnce(async ({ url }) => {
if (url?.includes("dev.0xkvn.eth?challenge=0x1dad95c4")) {
return {
data: {
payload:
"01010302010113010314010112041dad95c421013c200930786b766e2e6574682214b0b5b0106d69fe64545a60a68c014f7570d3f86115463044022075f4fffb553cb615a6adcecac60ce57f72b5ed76a73b18ca99e8914529efaea70220031df5f609e06d26d1f4b55605f483977e08406528c4ceab729d010d52725dd2",
},
};
}
});
const transport = await openTransportReplayer(
RecordStore.fromString(`
=> e020000000
<= 1dad95c49000
=> e022010080007e01010302010113010314010112041dad95c421013c200930786b766e2e6574682214b0b5b0106d69fe64545a60a68c014f7570d3f86115463044022075f4fffb553cb615a6adcecac60ce57f72b5ed76a73b18ca99e8914529efaea70220031df5f609e06d26d1f4b55605f483977e08406528c4ceab729d010d52725dd2
<= 9000
=> e00a000068054d415449437d1afa7b718fb893db30a