@shapeshiftoss/hdwallet-metamask-multichain 1.55.10-mipd.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/dist/adapter.d.ts +11 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +95 -0
- package/dist/adapter.js.map +1 -0
- package/dist/bitcoin.d.ts +8 -0
- package/dist/bitcoin.d.ts.map +1 -0
- package/dist/bitcoin.js +43 -0
- package/dist/bitcoin.js.map +1 -0
- package/dist/bitcoincash.d.ts +8 -0
- package/dist/bitcoincash.d.ts.map +1 -0
- package/dist/bitcoincash.js +43 -0
- package/dist/bitcoincash.js.map +1 -0
- package/dist/common.d.ts +2 -0
- package/dist/common.d.ts.map +1 -0
- package/dist/common.js +6 -0
- package/dist/common.js.map +1 -0
- package/dist/cosmos.d.ts +7 -0
- package/dist/cosmos.d.ts.map +1 -0
- package/dist/cosmos.js +64 -0
- package/dist/cosmos.js.map +1 -0
- package/dist/dogecoin.d.ts +8 -0
- package/dist/dogecoin.d.ts.map +1 -0
- package/dist/dogecoin.js +43 -0
- package/dist/dogecoin.js.map +1 -0
- package/dist/ethereum.d.ts +9 -0
- package/dist/ethereum.d.ts.map +1 -0
- package/dist/ethereum.js +159 -0
- package/dist/ethereum.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/litecoin.d.ts +8 -0
- package/dist/litecoin.d.ts.map +1 -0
- package/dist/litecoin.js +43 -0
- package/dist/litecoin.js.map +1 -0
- package/dist/shapeshift-multichain.d.ts +203 -0
- package/dist/shapeshift-multichain.d.ts.map +1 -0
- package/dist/shapeshift-multichain.js +883 -0
- package/dist/shapeshift-multichain.js.map +1 -0
- package/dist/thorchain.d.ts +7 -0
- package/dist/thorchain.d.ts.map +1 -0
- package/dist/thorchain.js +64 -0
- package/dist/thorchain.js.map +1 -0
- package/dist/utxo.d.ts +6 -0
- package/dist/utxo.d.ts.map +1 -0
- package/dist/utxo.js +205 -0
- package/dist/utxo.js.map +1 -0
- package/package.json +32 -0
- package/src/adapter.ts +62 -0
- package/src/bitcoin.ts +32 -0
- package/src/bitcoincash.ts +32 -0
- package/src/common.ts +2 -0
- package/src/cosmos.ts +30 -0
- package/src/dogecoin.ts +32 -0
- package/src/ethereum.ts +125 -0
- package/src/index.ts +2 -0
- package/src/litecoin.ts +31 -0
- package/src/shapeshift-multichain.test.ts +170 -0
- package/src/shapeshift-multichain.ts +871 -0
- package/src/thorchain.ts +30 -0
- package/src/utxo.ts +201 -0
- package/tsconfig.json +10 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/yarn-error.log +18555 -0
package/src/ethereum.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as core from "@shapeshiftoss/hdwallet-core";
|
|
2
|
+
import { ETHSignedMessage } from "@shapeshiftoss/hdwallet-core";
|
|
3
|
+
import { isHexString } from "ethers/lib/utils";
|
|
4
|
+
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
6
|
+
export async function ethVerifyMessage(msg: core.ETHVerifyMessage, ethereum: any): Promise<boolean | null> {
|
|
7
|
+
console.error("Method ethVerifyMessage unsupported for MetaMask wallet!");
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function ethGetAccountPaths(msg: core.ETHGetAccountPath): Array<core.ETHAccountPath> {
|
|
12
|
+
const slip44 = core.slip44ByCoin(msg.coin);
|
|
13
|
+
if (slip44 === undefined) return [];
|
|
14
|
+
return [
|
|
15
|
+
{
|
|
16
|
+
addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0],
|
|
17
|
+
hardenedPath: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx],
|
|
18
|
+
relPath: [0, 0],
|
|
19
|
+
description: "MetaMask(Shapeshift Multichain)",
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
25
|
+
export async function ethSignTx(msg: core.ETHSignTx, ethereum: any, from: string): Promise<core.ETHSignedTx | null> {
|
|
26
|
+
console.error("Method ethSignTx unsupported for MetaMask wallet!");
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function ethSendTx(msg: core.ETHSignTx, ethereum: any, from: string): Promise<core.ETHTxHash | null> {
|
|
31
|
+
try {
|
|
32
|
+
const utxBase = {
|
|
33
|
+
from: from,
|
|
34
|
+
to: msg.to,
|
|
35
|
+
value: msg.value,
|
|
36
|
+
data: msg.data,
|
|
37
|
+
chainId: msg.chainId,
|
|
38
|
+
nonce: msg.nonce,
|
|
39
|
+
// MetaMask, like other Web3 libraries, derives its transaction schema from Ethereum's official JSON-RPC API specification
|
|
40
|
+
// (https://github.com/ethereum/execution-apis/blob/d63d2a02bcd2a8cef54ae2fc5bbff8b4fac944eb/src/schemas/transaction.json).
|
|
41
|
+
// That schema defines the use of the label `gas` to set the transaction's gas limit and not `gasLimit` as used in other
|
|
42
|
+
// libraries and as stated in the official yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf).
|
|
43
|
+
gas: msg.gasLimit,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const utx = msg.maxFeePerGas
|
|
47
|
+
? {
|
|
48
|
+
...utxBase,
|
|
49
|
+
maxFeePerGas: msg.maxFeePerGas,
|
|
50
|
+
maxPriorityFeePerGas: msg.maxPriorityFeePerGas,
|
|
51
|
+
}
|
|
52
|
+
: { ...utxBase, gasPrice: msg.gasPrice };
|
|
53
|
+
|
|
54
|
+
const signedTx = await ethereum.request({
|
|
55
|
+
method: "eth_sendTransaction",
|
|
56
|
+
params: [utx],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
hash: signedTx,
|
|
61
|
+
} as core.ETHTxHash;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error(error);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function ethSignMessage(
|
|
69
|
+
msg: core.ETHSignMessage,
|
|
70
|
+
ethereum: any,
|
|
71
|
+
address: string
|
|
72
|
+
): Promise<core.ETHSignedMessage | null> {
|
|
73
|
+
try {
|
|
74
|
+
if (!isHexString(msg.message)) throw new Error("data is not an hex string");
|
|
75
|
+
const signedMsg = await ethereum.request({
|
|
76
|
+
method: "personal_sign",
|
|
77
|
+
params: [msg.message, address],
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
address: address,
|
|
82
|
+
signature: signedMsg,
|
|
83
|
+
} as ETHSignedMessage;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error(error);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function ethSignTypedData(
|
|
91
|
+
msg: core.ETHSignTypedData,
|
|
92
|
+
ethereum: any,
|
|
93
|
+
address: string
|
|
94
|
+
): Promise<core.ETHSignedMessage | null> {
|
|
95
|
+
try {
|
|
96
|
+
const signedMsg = await ethereum.request({
|
|
97
|
+
method: "eth_signTypedData_v4",
|
|
98
|
+
params: [address, JSON.stringify(msg.typedData)],
|
|
99
|
+
from: address,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
address: address,
|
|
104
|
+
signature: signedMsg,
|
|
105
|
+
} as ETHSignedMessage;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error(error);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function ethGetAddress(ethereum: any): Promise<string | null> {
|
|
113
|
+
if (!(ethereum && ethereum.request)) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const ethAccounts = await ethereum.request({
|
|
118
|
+
method: "eth_accounts",
|
|
119
|
+
});
|
|
120
|
+
return ethAccounts[0];
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error(error);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
package/src/index.ts
ADDED
package/src/litecoin.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as core from "@shapeshiftoss/hdwallet-core";
|
|
2
|
+
import {
|
|
3
|
+
LTCGetAddress as snapLitecoinGetAddress,
|
|
4
|
+
LTCGetPublicKeys as snapLitecoinGetPublicKeys,
|
|
5
|
+
LTCSignTransaction as snapLitecoinSignTransaction,
|
|
6
|
+
} from "@shapeshiftoss/metamask-snaps-adapter";
|
|
7
|
+
import { BitcoinGetPublicKeysResponse, LitecoinGetAddressResponse } from "@shapeshiftoss/metamask-snaps-types";
|
|
8
|
+
|
|
9
|
+
import { SNAP_ID } from "./common";
|
|
10
|
+
import { utxoGetAccountPaths } from "./utxo";
|
|
11
|
+
|
|
12
|
+
export function litecoinGetAccountPaths(msg: core.BTCGetAccountPaths): Array<core.BTCAccountPath> {
|
|
13
|
+
return utxoGetAccountPaths(msg);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
17
|
+
export function litecoinNextAccountPath(msg: core.BTCAccountPath): core.BTCAccountPath | undefined {
|
|
18
|
+
// Only support one account for now (like portis).
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function litecoinGetAddress(msg: core.BTCGetAddress): Promise<LitecoinGetAddressResponse> {
|
|
23
|
+
return await snapLitecoinGetAddress({ snapId: SNAP_ID, addressParams: msg });
|
|
24
|
+
}
|
|
25
|
+
export async function litecoinGetPublicKeys(msg: core.BTCGetAddress): Promise<BitcoinGetPublicKeysResponse> {
|
|
26
|
+
return await snapLitecoinGetPublicKeys({ snapId: SNAP_ID, addressParams: msg });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function litecoinSignTx(msg: core.BTCSignTx): Promise<core.BTCSignedTx | null> {
|
|
30
|
+
return await snapLitecoinSignTransaction({ snapId: SNAP_ID, transaction: msg });
|
|
31
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import * as core from "@shapeshiftoss/hdwallet-core";
|
|
2
|
+
|
|
3
|
+
import { MetaMaskShapeShiftMultiChainHDWallet, MetaMaskShapeShiftMultiChainHDWalletInfo } from ".";
|
|
4
|
+
|
|
5
|
+
describe("HDWalletInfo", () => {
|
|
6
|
+
const info = new MetaMaskShapeShiftMultiChainHDWalletInfo();
|
|
7
|
+
|
|
8
|
+
it("should have correct metadata", async () => {
|
|
9
|
+
expect(info.getVendor()).toBe("MetaMask");
|
|
10
|
+
expect(info.hasOnDevicePinEntry()).toBe(false);
|
|
11
|
+
expect(info.hasOnDevicePassphrase()).toBe(true);
|
|
12
|
+
expect(info.hasOnDeviceDisplay()).toBe(true);
|
|
13
|
+
expect(info.hasOnDeviceRecovery()).toBe(true);
|
|
14
|
+
expect(await info.ethSupportsNetwork(1)).toBe(true);
|
|
15
|
+
expect(await info.ethSupportsSecureTransfer()).toBe(false);
|
|
16
|
+
expect(info.ethSupportsNativeShapeShift()).toBe(false);
|
|
17
|
+
expect(await info.ethSupportsEIP1559()).toBe(true);
|
|
18
|
+
expect(await info.supportsOfflineSigning()).toBe(false);
|
|
19
|
+
expect(await info.supportsBroadcast()).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("MetaMaskShapeShiftMultiChainHDWallet", () => {
|
|
24
|
+
let wallet: MetaMaskShapeShiftMultiChainHDWallet;
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
wallet = new MetaMaskShapeShiftMultiChainHDWallet(
|
|
27
|
+
core.untouchable("MetaMaskShapeShiftMultiChainHDWallet:provider")
|
|
28
|
+
);
|
|
29
|
+
wallet.ethAddress = "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8";
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("should match the metadata", async () => {
|
|
33
|
+
expect(wallet.getVendor()).toBe("MetaMask");
|
|
34
|
+
expect(wallet.hasOnDevicePinEntry()).toBe(false);
|
|
35
|
+
expect(wallet.hasOnDevicePassphrase()).toBe(true);
|
|
36
|
+
expect(wallet.hasOnDeviceDisplay()).toBe(true);
|
|
37
|
+
expect(wallet.hasOnDeviceRecovery()).toBe(true);
|
|
38
|
+
expect(await wallet.ethSupportsNetwork(1)).toBe(true);
|
|
39
|
+
expect(await wallet.ethSupportsSecureTransfer()).toBe(false);
|
|
40
|
+
expect(wallet.ethSupportsNativeShapeShift()).toBe(false);
|
|
41
|
+
expect(await wallet.ethSupportsEIP1559()).toBe(true);
|
|
42
|
+
expect(await wallet.supportsOfflineSigning()).toBe(false);
|
|
43
|
+
expect(wallet.supportsBip44Accounts()).toBe(false);
|
|
44
|
+
expect(await wallet.supportsBroadcast()).toBe(true);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should test ethSignMessage", async () => {
|
|
48
|
+
wallet.provider = {
|
|
49
|
+
request: jest.fn().mockReturnValue(
|
|
50
|
+
`Object {
|
|
51
|
+
"address": "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8",
|
|
52
|
+
"signature": "0x05f51140905ffa33ffdc57f46b0b8d8fbb1d2a99f8cd843ca27893c01c31351c08b76d83dce412731c846e3b50649724415deb522d00950fbf4f2c1459c2b70b1b",
|
|
53
|
+
}`
|
|
54
|
+
),
|
|
55
|
+
};
|
|
56
|
+
const msg = "0x737570657220736563726574206d657373616765"; // super secret message
|
|
57
|
+
expect(
|
|
58
|
+
await wallet.ethSignMessage({
|
|
59
|
+
addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
|
|
60
|
+
message: msg,
|
|
61
|
+
})
|
|
62
|
+
).toMatchInlineSnapshot(`
|
|
63
|
+
Object {
|
|
64
|
+
"address": "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8",
|
|
65
|
+
"signature": "Object {
|
|
66
|
+
\\"address\\": \\"0x73d0385F4d8E00C5e6504C6030F47BF6212736A8\\",
|
|
67
|
+
\\"signature\\": \\"0x05f51140905ffa33ffdc57f46b0b8d8fbb1d2a99f8cd843ca27893c01c31351c08b76d83dce412731c846e3b50649724415deb522d00950fbf4f2c1459c2b70b1b\\",
|
|
68
|
+
}",
|
|
69
|
+
}
|
|
70
|
+
`);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("ethSignMessage returns null on error", async () => {
|
|
74
|
+
wallet.provider = {
|
|
75
|
+
request: jest.fn().mockRejectedValue(new Error("An Error has occurred")),
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const msg = "0x737570657220736563726574206d657373616765"; // super secret message
|
|
79
|
+
const sig = await wallet.ethSignMessage({
|
|
80
|
+
addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
|
|
81
|
+
message: msg,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
expect(sig).toBe(null);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("ethGetAddress returns a valid address", async () => {
|
|
88
|
+
wallet.provider = {
|
|
89
|
+
request: jest.fn().mockReturnValue(["0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"]),
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const msg = "0x737570657220736563726574206d657373616765"; // super secret message
|
|
93
|
+
const sig = await wallet.ethSignMessage({
|
|
94
|
+
addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
|
|
95
|
+
message: msg,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
expect(sig).toMatchObject({
|
|
99
|
+
address: "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8",
|
|
100
|
+
signature: ["0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"],
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
it("ethSendTx returns a valid hash", async () => {
|
|
104
|
+
wallet.provider = {
|
|
105
|
+
request: jest.fn().mockReturnValue("0x123"),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const hash = await wallet.ethSendTx({
|
|
109
|
+
addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
|
|
110
|
+
nonce: "0xDEADBEEF",
|
|
111
|
+
gasPrice: "0xDEADBEEF",
|
|
112
|
+
gasLimit: "0xDEADBEEF",
|
|
113
|
+
to: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
|
114
|
+
value: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
|
115
|
+
data: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
|
116
|
+
chainId: 1,
|
|
117
|
+
});
|
|
118
|
+
expect(wallet.provider.request).toHaveBeenCalled();
|
|
119
|
+
expect(hash).toMatchObject({ hash: "0x123" });
|
|
120
|
+
});
|
|
121
|
+
it("ethSendTx returns a valid hash if maxFeePerGas is present in msg", async () => {
|
|
122
|
+
wallet.provider = {
|
|
123
|
+
request: jest.fn().mockReturnValue("0x123"),
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const hash = await wallet.ethSendTx({
|
|
127
|
+
addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
|
|
128
|
+
nonce: "0xDEADBEEF",
|
|
129
|
+
gasLimit: "0xDEADBEEF",
|
|
130
|
+
maxFeePerGas: "0xDEADBEEF",
|
|
131
|
+
to: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
|
132
|
+
value: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
|
133
|
+
data: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
|
134
|
+
chainId: 1,
|
|
135
|
+
});
|
|
136
|
+
expect(wallet.provider.request).toHaveBeenCalled();
|
|
137
|
+
expect(hash).toMatchObject({ hash: "0x123" });
|
|
138
|
+
});
|
|
139
|
+
it("ethSendTx returns null on error", async () => {
|
|
140
|
+
wallet.provider = {
|
|
141
|
+
request: jest.fn().mockRejectedValue(new Error("An Error has occurred")),
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const hash = await wallet.ethSendTx({
|
|
145
|
+
addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
|
|
146
|
+
nonce: "0xDEADBEEF",
|
|
147
|
+
gasPrice: "0xDEADBEEF",
|
|
148
|
+
gasLimit: "0xDEADBEEF",
|
|
149
|
+
to: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
|
150
|
+
value: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
|
151
|
+
data: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
|
152
|
+
chainId: 1,
|
|
153
|
+
});
|
|
154
|
+
expect(wallet.provider.request).toHaveBeenCalled();
|
|
155
|
+
expect(hash).toBe(null);
|
|
156
|
+
});
|
|
157
|
+
it("ethVerifyMessage returns null as its not implemented", async () => {
|
|
158
|
+
wallet.provider = {
|
|
159
|
+
request: jest.fn().mockReturnValue("0x3f2329C9ADFbcCd9A84f52c906E936A42dA18CB8"),
|
|
160
|
+
};
|
|
161
|
+
expect(
|
|
162
|
+
await wallet.ethVerifyMessage({
|
|
163
|
+
address: "0x3f2329C9ADFbcCd9A84f52c906E936A42dA18CB8",
|
|
164
|
+
message: "hello world",
|
|
165
|
+
signature:
|
|
166
|
+
"0x29f7212ecc1c76cea81174af267b67506f754ea8c73f144afa900a0d85b24b21319621aeb062903e856352f38305710190869c3ce5a1425d65ef4fa558d0fc251b",
|
|
167
|
+
})
|
|
168
|
+
).toEqual(null);
|
|
169
|
+
});
|
|
170
|
+
});
|