@swapkit/wallet-hardware 4.9.34 → 4.11.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/dist/chunk-9gy0xve4.js +4 -0
- package/dist/{chunk-qs60k0yv.js.map → chunk-9gy0xve4.js.map} +3 -3
- package/dist/ledger/index.cjs +2 -2
- package/dist/ledger/index.cjs.map +8 -7
- package/dist/ledger/index.js +2 -2
- package/dist/ledger/index.js.map +8 -7
- package/dist/trezor/index.cjs +2 -2
- package/dist/trezor/index.cjs.map +4 -4
- package/dist/trezor/index.js +2 -2
- package/dist/trezor/index.js.map +3 -3
- package/dist/types/ledger/clients/evm.d.ts +4 -0
- package/dist/types/ledger/clients/evm.d.ts.map +1 -1
- package/dist/types/ledger/helpers/getLedgerAddress.d.ts.map +1 -1
- package/dist/types/ledger/helpers/getLedgerClient.d.ts +2 -1
- package/dist/types/ledger/helpers/getLedgerClient.d.ts.map +1 -1
- package/dist/types/ledger/helpers/ledgerNetworkInfo.d.ts +14 -0
- package/dist/types/ledger/helpers/ledgerNetworkInfo.d.ts.map +1 -0
- package/dist/types/ledger/index.d.ts +2 -2
- package/dist/types/ledger/index.d.ts.map +1 -1
- package/dist/types/trezor/evmSigner.d.ts.map +1 -1
- package/dist/types/trezor/index.d.ts +2 -2
- package/dist/types/trezor/index.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/ledger/clients/evm.ts +85 -2
- package/src/ledger/helpers/getLedgerAddress.ts +1 -0
- package/src/ledger/helpers/getLedgerClient.ts +4 -0
- package/src/ledger/helpers/ledgerNetworkInfo.ts +127 -0
- package/src/ledger/index.ts +3 -0
- package/src/trezor/evmSigner.ts +3 -4
- package/src/trezor/index.ts +3 -0
- package/dist/chunk-qs60k0yv.js +0 -4
|
@@ -15,9 +15,9 @@ export declare const trezorWallet: {
|
|
|
15
15
|
}) => (chains: Chain[], derivationPath: readonly [44, 118, 0, 0, 0] | readonly [44, 931, 0, 0, 0] | readonly [number, number, number, number, number] | readonly [44, 683, 0, 0] | readonly [44, 637, 0, 0, 0] | readonly [44, 60, 0, 0, 0] | readonly [44, 397, 0, 0, 0] | readonly [0, 0, 0, 0, 0] | readonly [44, 144, 0, 0, 0] | readonly [44, 501, 0, 0, 0] | readonly [8797555, 1, 0, 0, 0] | readonly [44, 607, 0, 0, 0] | readonly [44, 195, 0, 0, 0] | readonly [44, 148, 0, 0, 0] | readonly [44, 784, 0, 0, 0] | readonly [1852, 1815, 0, 0, 0] | readonly [44, 9004, 0, 0, 0] | readonly [number, number, number, number, (number | undefined)?] | readonly [44, 145, 0, 0, 0] | readonly [84, 2, 0, 0, 0] | readonly [44, 3, 0, 0, 0] | readonly [44, 5, 0, 0, 0] | readonly [44, 133, 0, 0, 0], params_2?: ConnectTrezorOptions | undefined) => Promise<boolean>;
|
|
16
16
|
directSigningSupport: import("@swapkit/wallet-core").DirectSigningSupport;
|
|
17
17
|
getExtendedPublicKey?: import("@swapkit/wallet-core").GetExtendedPublicKey;
|
|
18
|
-
supportedChains: (Chain.Arbitrum | Chain.Aurora | Chain.Avalanche | Chain.Base | Chain.Berachain | Chain.BinanceSmartChain | Chain.Bitcoin | Chain.BitcoinCash | Chain.Dash | Chain.Dogecoin | Chain.Ethereum | Chain.Gnosis | Chain.Litecoin | Chain.Monad | Chain.Optimism | Chain.Polygon | Chain.XLayer | Chain.Zcash)[];
|
|
18
|
+
supportedChains: (Chain.Arbitrum | Chain.Arc | Chain.Aurora | Chain.Avalanche | Chain.Base | Chain.Berachain | Chain.BinanceSmartChain | Chain.Bitcoin | Chain.BitcoinCash | Chain.Dash | Chain.Dogecoin | Chain.Ethereum | Chain.Gnosis | Chain.Litecoin | Chain.Monad | Chain.Optimism | Chain.Polygon | Chain.XLayer | Chain.Zcash)[];
|
|
19
19
|
};
|
|
20
20
|
};
|
|
21
|
-
export declare const TREZOR_SUPPORTED_CHAINS: (Chain.Arbitrum | Chain.Aurora | Chain.Avalanche | Chain.Base | Chain.Berachain | Chain.BinanceSmartChain | Chain.Bitcoin | Chain.BitcoinCash | Chain.Dash | Chain.Dogecoin | Chain.Ethereum | Chain.Gnosis | Chain.Litecoin | Chain.Monad | Chain.Optimism | Chain.Polygon | Chain.XLayer | Chain.Zcash)[];
|
|
21
|
+
export declare const TREZOR_SUPPORTED_CHAINS: (Chain.Arbitrum | Chain.Arc | Chain.Aurora | Chain.Avalanche | Chain.Base | Chain.Berachain | Chain.BinanceSmartChain | Chain.Bitcoin | Chain.BitcoinCash | Chain.Dash | Chain.Dogecoin | Chain.Ethereum | Chain.Gnosis | Chain.Litecoin | Chain.Monad | Chain.Optimism | Chain.Polygon | Chain.XLayer | Chain.Zcash)[];
|
|
22
22
|
export {};
|
|
23
23
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/trezor/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,EACL,KAAK,mBAAmB,EAQxB,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAC;AAa1B,OAAO,EAA0C,KAAK,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAKlH,KAAK,oBAAoB,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAgIjD,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,UA6B9E;AAqED,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,2BAS1E;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/trezor/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,EACL,KAAK,mBAAmB,EAQxB,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAC;AAa1B,OAAO,EAA0C,KAAK,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAKlH,KAAK,oBAAoB,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAgIjD,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,UA6B9E;AAqED,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,2BAS1E;AAi9BD,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,KAAK,EACZ,cAAc,CAAC,EAAE,mBAAmB,EACpC,EAAE,YAAY,EAAE,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/C,OAAO,CAAC,6BAA6B,GAAG,SAAS,CAAC,CA0CpD;AAED,eAAO,MAAM,YAAY;;;;;;;;;CAiHvB,CAAC;AAEH,eAAO,MAAM,uBAAuB,yTAAyC,CAAC"}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"@ledgerhq/errors": "~6.29.0",
|
|
10
10
|
"@ledgerhq/hw-app-btc": "~10.17.0",
|
|
11
11
|
"@ledgerhq/hw-app-cosmos": "~6.33.0",
|
|
12
|
-
"@ledgerhq/hw-app-eth": "~7.
|
|
12
|
+
"@ledgerhq/hw-app-eth": "~7.8.18",
|
|
13
13
|
"@ledgerhq/hw-app-near": "~6.32.0",
|
|
14
14
|
"@ledgerhq/hw-app-sui": "~1.5.0",
|
|
15
15
|
"@ledgerhq/hw-app-trx": "~6.32.0",
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"@near-js/transactions": "~2.5.0",
|
|
23
23
|
"@scure/base": "2.2.0",
|
|
24
24
|
"@scure/bip32": "2.2.0",
|
|
25
|
-
"@swapkit/helpers": "^5.
|
|
26
|
-
"@swapkit/toolboxes": "^5.
|
|
27
|
-
"@swapkit/utxo-signer": "^3.
|
|
28
|
-
"@swapkit/wallet-core": "^5.0.
|
|
25
|
+
"@swapkit/helpers": "^5.4.1",
|
|
26
|
+
"@swapkit/toolboxes": "^5.4.1",
|
|
27
|
+
"@swapkit/utxo-signer": "^3.1.0",
|
|
28
|
+
"@swapkit/wallet-core": "^5.0.8",
|
|
29
29
|
"@trezor/connect-web": "~9.7.3",
|
|
30
30
|
"cosmjs-types": "~0.10.1",
|
|
31
31
|
"ethers": "^6.14.0",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@ledgerhq/errors": "6.29.0",
|
|
45
45
|
"@ledgerhq/hw-app-btc": "10.17.0",
|
|
46
46
|
"@ledgerhq/hw-app-cosmos": "6.33.0",
|
|
47
|
-
"@ledgerhq/hw-app-eth": "7.
|
|
47
|
+
"@ledgerhq/hw-app-eth": "7.8.18",
|
|
48
48
|
"@ledgerhq/hw-app-near": "6.32.0",
|
|
49
49
|
"@ledgerhq/hw-app-sui": "1.5.0",
|
|
50
50
|
"@ledgerhq/hw-app-trx": "6.32.0",
|
|
@@ -109,5 +109,5 @@
|
|
|
109
109
|
"type-check:go": "tsgo"
|
|
110
110
|
},
|
|
111
111
|
"type": "module",
|
|
112
|
-
"version": "4.
|
|
112
|
+
"version": "4.11.0"
|
|
113
113
|
}
|
|
@@ -16,6 +16,32 @@ import {
|
|
|
16
16
|
} from "ethers";
|
|
17
17
|
|
|
18
18
|
import { getLedgerTransport } from "../helpers/getLedgerTransport";
|
|
19
|
+
import {
|
|
20
|
+
fetchLedgerNetworkCertificate,
|
|
21
|
+
fetchLedgerNetworkDescriptor,
|
|
22
|
+
provideLedgerCertificate,
|
|
23
|
+
provideLedgerNetworkInformation,
|
|
24
|
+
} from "../helpers/ledgerNetworkInfo";
|
|
25
|
+
|
|
26
|
+
const LEDGER_INCORRECT_DATA = 0x6a80;
|
|
27
|
+
|
|
28
|
+
const ARC_CHAIN_ID = Number(ChainId.Arc);
|
|
29
|
+
|
|
30
|
+
type LedgerTransactionResolution = Awaited<
|
|
31
|
+
ReturnType<typeof import("@ledgerhq/hw-app-eth")["ledgerService"]["resolveTransaction"]>
|
|
32
|
+
>;
|
|
33
|
+
|
|
34
|
+
function isLedgerIncorrectDataError(error: unknown) {
|
|
35
|
+
return (
|
|
36
|
+
error instanceof Error &&
|
|
37
|
+
"statusCode" in error &&
|
|
38
|
+
(error as { statusCode: number }).statusCode === LEDGER_INCORRECT_DATA
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function hasClearSigningPayload(resolution: LedgerTransactionResolution | null) {
|
|
43
|
+
return Object.values(resolution ?? {}).some((entries) => Array.isArray(entries) && entries.length);
|
|
44
|
+
}
|
|
19
45
|
|
|
20
46
|
function parseLedgerSignatureV(v: number | string) {
|
|
21
47
|
if (typeof v === "number") return v;
|
|
@@ -31,6 +57,7 @@ class EVMLedgerInterface extends AbstractSigner {
|
|
|
31
57
|
ledgerTimeout = 50000;
|
|
32
58
|
private transport?: Transport;
|
|
33
59
|
private readonly injectedTransport?: Transport;
|
|
60
|
+
private arcNetworkRegistered = false;
|
|
34
61
|
|
|
35
62
|
constructor({
|
|
36
63
|
provider,
|
|
@@ -172,9 +199,22 @@ class EVMLedgerInterface extends AbstractSigner {
|
|
|
172
199
|
|
|
173
200
|
const { ledgerService } = await import("@ledgerhq/hw-app-eth");
|
|
174
201
|
|
|
175
|
-
const
|
|
202
|
+
const chainId = Number(baseTx.chainId);
|
|
203
|
+
const isArc = chainId === ARC_CHAIN_ID;
|
|
204
|
+
|
|
205
|
+
const resolution = await ledgerService
|
|
206
|
+
.resolveTransaction(unsignedTx, {}, { erc20: true, externalPlugins: true })
|
|
207
|
+
.catch((error) => {
|
|
208
|
+
if (!isArc) throw error;
|
|
209
|
+
|
|
210
|
+
console.warn("Ledger: could not fetch clear-signing metadata for Arc, signing blind");
|
|
211
|
+
|
|
212
|
+
return null;
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
if (isArc && !this.arcNetworkRegistered) await this.registerNetworkOnDevice(chainId);
|
|
176
216
|
|
|
177
|
-
const signature = await this.
|
|
217
|
+
const signature = await this.signWithLedgerApp(unsignedTx, resolution, chainId);
|
|
178
218
|
|
|
179
219
|
if (!signature) throw new SwapKitError("wallet_ledger_signing_error");
|
|
180
220
|
|
|
@@ -183,12 +223,55 @@ class EVMLedgerInterface extends AbstractSigner {
|
|
|
183
223
|
return Transaction.from({ ...baseTx, signature: { r: `0x${r}`, s: `0x${s}`, v: parseLedgerSignatureV(v) } })
|
|
184
224
|
.serialized;
|
|
185
225
|
};
|
|
226
|
+
|
|
227
|
+
private signWithLedgerApp = async (
|
|
228
|
+
unsignedTx: string,
|
|
229
|
+
resolution: LedgerTransactionResolution | null,
|
|
230
|
+
chainId: number,
|
|
231
|
+
) => {
|
|
232
|
+
try {
|
|
233
|
+
return await this.ledgerApp?.signTransaction(this.derivationPath, unsignedTx, resolution);
|
|
234
|
+
} catch (error) {
|
|
235
|
+
const canSignBlind =
|
|
236
|
+
chainId === ARC_CHAIN_ID && isLedgerIncorrectDataError(error) && hasClearSigningPayload(resolution);
|
|
237
|
+
|
|
238
|
+
if (!canSignBlind) throw error;
|
|
239
|
+
|
|
240
|
+
console.warn("Ledger: the app rejected the Arc metadata, signing blind");
|
|
241
|
+
|
|
242
|
+
return await this.ledgerApp?.signTransaction(this.derivationPath, unsignedTx, null);
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
private registerNetworkOnDevice = async (chainId: number) => {
|
|
247
|
+
const deviceModelId = this.transport?.deviceModel?.id;
|
|
248
|
+
|
|
249
|
+
if (!(this.transport && deviceModelId)) return;
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
const [descriptor, certificate] = await Promise.all([
|
|
253
|
+
fetchLedgerNetworkDescriptor(chainId, deviceModelId),
|
|
254
|
+
fetchLedgerNetworkCertificate(deviceModelId),
|
|
255
|
+
]);
|
|
256
|
+
|
|
257
|
+
if (!descriptor) return;
|
|
258
|
+
|
|
259
|
+
if (certificate) await provideLedgerCertificate(this.transport, certificate);
|
|
260
|
+
|
|
261
|
+
await provideLedgerNetworkInformation(this.transport, descriptor);
|
|
262
|
+
|
|
263
|
+
this.arcNetworkRegistered = true;
|
|
264
|
+
} catch {
|
|
265
|
+
// the app will reject the metadata and signWithLedgerApp falls back to blind signing
|
|
266
|
+
}
|
|
267
|
+
};
|
|
186
268
|
}
|
|
187
269
|
|
|
188
270
|
type LedgerParams = { provider: Provider; derivationPath?: DerivationPathArray; transport?: Transport };
|
|
189
271
|
|
|
190
272
|
export const ArbitrumLedger = (params: LedgerParams) =>
|
|
191
273
|
new EVMLedgerInterface({ ...params, chainId: ChainId.Arbitrum });
|
|
274
|
+
export const ArcLedger = (params: LedgerParams) => new EVMLedgerInterface({ ...params, chainId: ChainId.Arc });
|
|
192
275
|
export const AuroraLedger = (params: LedgerParams) => new EVMLedgerInterface({ ...params, chainId: ChainId.Aurora });
|
|
193
276
|
export const AvalancheLedger = (params: LedgerParams) =>
|
|
194
277
|
new EVMLedgerInterface({ ...params, chainId: ChainId.Avalanche });
|
|
@@ -4,6 +4,7 @@ import { Chain, type DerivationPathArray, type EVMChain, SwapKitError, WalletOpt
|
|
|
4
4
|
import { CosmosLedger } from "../clients/cosmos";
|
|
5
5
|
import {
|
|
6
6
|
ArbitrumLedger,
|
|
7
|
+
ArcLedger,
|
|
7
8
|
AuroraLedger,
|
|
8
9
|
AvalancheLedger,
|
|
9
10
|
BaseLedger,
|
|
@@ -32,6 +33,7 @@ import { XRPLedger } from "../clients/xrp";
|
|
|
32
33
|
|
|
33
34
|
type LedgerSignerMap = {
|
|
34
35
|
[Chain.Arbitrum]: ReturnType<typeof ArbitrumLedger>;
|
|
36
|
+
[Chain.Arc]: ReturnType<typeof ArcLedger>;
|
|
35
37
|
[Chain.Aurora]: ReturnType<typeof AuroraLedger>;
|
|
36
38
|
[Chain.Avalanche]: ReturnType<typeof AvalancheLedger>;
|
|
37
39
|
[Chain.Base]: ReturnType<typeof BaseLedger>;
|
|
@@ -94,6 +96,7 @@ export const getLedgerClient = async <T extends LedgerSupportedChain>({
|
|
|
94
96
|
})
|
|
95
97
|
.with(
|
|
96
98
|
Chain.Arbitrum,
|
|
99
|
+
Chain.Arc,
|
|
97
100
|
Chain.Aurora,
|
|
98
101
|
Chain.Avalanche,
|
|
99
102
|
Chain.Berachain,
|
|
@@ -113,6 +116,7 @@ export const getLedgerClient = async <T extends LedgerSupportedChain>({
|
|
|
113
116
|
.with(Chain.BinanceSmartChain, () => BinanceSmartChainLedger(params) as LedgerSignerMap[T])
|
|
114
117
|
.with(Chain.Avalanche, () => AvalancheLedger(params) as LedgerSignerMap[T])
|
|
115
118
|
.with(Chain.Arbitrum, () => ArbitrumLedger(params) as LedgerSignerMap[T])
|
|
119
|
+
.with(Chain.Arc, () => ArcLedger(params) as LedgerSignerMap[T])
|
|
116
120
|
.with(Chain.Berachain, () => BerachainLedger(params) as LedgerSignerMap[T])
|
|
117
121
|
.with(Chain.Optimism, () => OptimismLedger(params) as LedgerSignerMap[T])
|
|
118
122
|
.with(Chain.Polygon, () => PolygonLedger(params) as LedgerSignerMap[T])
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type Transport from "@ledgerhq/hw-transport";
|
|
2
|
+
|
|
3
|
+
const LEDGER_CAL_SERVICE_URL = "https://crypto-assets-service.api.ledger.com/v1";
|
|
4
|
+
|
|
5
|
+
const LEDGER_DEVICE_TO_CAL_MODEL: Record<string, string> = {
|
|
6
|
+
apex: "apexp",
|
|
7
|
+
europa: "flex",
|
|
8
|
+
nanoS: "nanos",
|
|
9
|
+
nanoSP: "nanosp",
|
|
10
|
+
nanoX: "nanox",
|
|
11
|
+
stax: "stax",
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const APDU_CLA = 0xe0;
|
|
15
|
+
const APDU_CLA_PKI = 0xb0;
|
|
16
|
+
const APDU_INS_LOAD_CERTIFICATE = 0x06;
|
|
17
|
+
const LEDGER_KEY_USAGE_NETWORK = 0x0c;
|
|
18
|
+
const APDU_INS_PROVIDE_NETWORK_INFORMATION = 0x30;
|
|
19
|
+
const APDU_P1_FIRST_CHUNK = 0x01;
|
|
20
|
+
const APDU_P1_FOLLOWING_CHUNK = 0x00;
|
|
21
|
+
const APDU_P2_NETWORK_CONFIG = 0x00;
|
|
22
|
+
const APDU_P2_NETWORK_ICON = 0x01;
|
|
23
|
+
const APDU_MAX_CHUNK_SIZE = 0xff;
|
|
24
|
+
const TLV_TAG_DER_SIGNATURE = 0x15;
|
|
25
|
+
|
|
26
|
+
export type LedgerNetworkDescriptor = { data: string; icon?: string; signature: string };
|
|
27
|
+
|
|
28
|
+
type CalNetwork = {
|
|
29
|
+
chain_id: number;
|
|
30
|
+
descriptors?: Record<string, { data?: string; signatures?: { prod?: string } }>;
|
|
31
|
+
icons?: Record<string, string>;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export async function fetchLedgerNetworkCertificate(
|
|
35
|
+
deviceModelId: string,
|
|
36
|
+
fetchFn: typeof fetch = fetch,
|
|
37
|
+
): Promise<string | null> {
|
|
38
|
+
const calModel = LEDGER_DEVICE_TO_CAL_MODEL[deviceModelId];
|
|
39
|
+
if (!calModel) return null;
|
|
40
|
+
|
|
41
|
+
const url = `${LEDGER_CAL_SERVICE_URL}/certificates?output=descriptor&public_key_usage=network&target_device=${calModel}`;
|
|
42
|
+
const response = await fetchFn(url);
|
|
43
|
+
if (!response.ok) return null;
|
|
44
|
+
|
|
45
|
+
const certificates = (await response.json()) as Array<{
|
|
46
|
+
descriptor?: { data?: string; signatures?: { prod?: string } };
|
|
47
|
+
}>;
|
|
48
|
+
const descriptor = certificates[0]?.descriptor;
|
|
49
|
+
const signature = descriptor?.signatures?.prod;
|
|
50
|
+
|
|
51
|
+
if (!(descriptor?.data && signature)) return null;
|
|
52
|
+
|
|
53
|
+
return `${descriptor.data}${appendSignatureTlv(signature)}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function provideLedgerCertificate(transport: Transport, payloadHex: string) {
|
|
57
|
+
await transport.send(
|
|
58
|
+
APDU_CLA_PKI,
|
|
59
|
+
APDU_INS_LOAD_CERTIFICATE,
|
|
60
|
+
LEDGER_KEY_USAGE_NETWORK,
|
|
61
|
+
0x00,
|
|
62
|
+
Buffer.from(payloadHex, "hex"),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function fetchLedgerNetworkDescriptor(
|
|
67
|
+
chainId: number,
|
|
68
|
+
deviceModelId: string,
|
|
69
|
+
fetchFn: typeof fetch = fetch,
|
|
70
|
+
): Promise<LedgerNetworkDescriptor | null> {
|
|
71
|
+
const calModel = LEDGER_DEVICE_TO_CAL_MODEL[deviceModelId];
|
|
72
|
+
if (!calModel) return null;
|
|
73
|
+
|
|
74
|
+
const url = `${LEDGER_CAL_SERVICE_URL}/networks?chain_id=${chainId}&output=chain_id,descriptors,icons`;
|
|
75
|
+
const response = await fetchFn(url);
|
|
76
|
+
if (!response.ok) return null;
|
|
77
|
+
|
|
78
|
+
const networks = (await response.json()) as CalNetwork[];
|
|
79
|
+
const network = networks.find((entry) => entry.chain_id === chainId);
|
|
80
|
+
const descriptor = network?.descriptors?.[calModel];
|
|
81
|
+
const signature = descriptor?.signatures?.prod;
|
|
82
|
+
|
|
83
|
+
if (!(descriptor?.data && signature)) return null;
|
|
84
|
+
|
|
85
|
+
return { data: descriptor.data, icon: network?.icons?.[calModel], signature };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function appendSignatureTlv(signature: string) {
|
|
89
|
+
return encodeTlv(TLV_TAG_DER_SIGNATURE, Buffer.from(signature, "hex")).toString("hex");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function encodeTlv(tag: number, value: Buffer) {
|
|
93
|
+
return Buffer.concat([Buffer.from([tag, value.length]), value]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function encodeNetworkInfoPayload({ data, signature }: LedgerNetworkDescriptor) {
|
|
97
|
+
const tlv = Buffer.concat([
|
|
98
|
+
Buffer.from(data, "hex"),
|
|
99
|
+
encodeTlv(TLV_TAG_DER_SIGNATURE, Buffer.from(signature, "hex")),
|
|
100
|
+
]);
|
|
101
|
+
const length = Buffer.alloc(2);
|
|
102
|
+
length.writeUInt16BE(tlv.length, 0);
|
|
103
|
+
return Buffer.concat([length, tlv]);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function sendChunked(transport: Transport, p2: number, payload: Buffer) {
|
|
107
|
+
for (let offset = 0; offset < payload.length; offset += APDU_MAX_CHUNK_SIZE) {
|
|
108
|
+
const p1 = offset === 0 ? APDU_P1_FIRST_CHUNK : APDU_P1_FOLLOWING_CHUNK;
|
|
109
|
+
const chunk = payload.subarray(offset, offset + APDU_MAX_CHUNK_SIZE);
|
|
110
|
+
await transport.send(APDU_CLA, APDU_INS_PROVIDE_NETWORK_INFORMATION, p1, p2, chunk);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function provideLedgerNetworkInformation(transport: Transport, descriptor: LedgerNetworkDescriptor) {
|
|
115
|
+
const payload = encodeNetworkInfoPayload(descriptor);
|
|
116
|
+
await sendChunked(transport, APDU_P2_NETWORK_CONFIG, payload);
|
|
117
|
+
|
|
118
|
+
if (!descriptor.icon) return { iconAccepted: false };
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
await sendChunked(transport, APDU_P2_NETWORK_ICON, Buffer.from(descriptor.icon, "hex"));
|
|
122
|
+
return { iconAccepted: true };
|
|
123
|
+
} catch {
|
|
124
|
+
await sendChunked(transport, APDU_P2_NETWORK_CONFIG, payload);
|
|
125
|
+
return { iconAccepted: false };
|
|
126
|
+
}
|
|
127
|
+
}
|
package/src/ledger/index.ts
CHANGED
|
@@ -60,6 +60,7 @@ export const ledgerWallet = createWallet({
|
|
|
60
60
|
},
|
|
61
61
|
directSigningSupport: {
|
|
62
62
|
[Chain.Arbitrum]: true,
|
|
63
|
+
[Chain.Arc]: true,
|
|
63
64
|
[Chain.Aurora]: true,
|
|
64
65
|
[Chain.Avalanche]: true,
|
|
65
66
|
[Chain.Base]: true,
|
|
@@ -88,6 +89,7 @@ export const ledgerWallet = createWallet({
|
|
|
88
89
|
name: "connectLedger",
|
|
89
90
|
supportedChains: [
|
|
90
91
|
Chain.Arbitrum,
|
|
92
|
+
Chain.Arc,
|
|
91
93
|
Chain.Aurora,
|
|
92
94
|
Chain.Avalanche,
|
|
93
95
|
Chain.Base,
|
|
@@ -400,6 +402,7 @@ async function getWalletMethods({
|
|
|
400
402
|
case Chain.Ethereum:
|
|
401
403
|
case Chain.Avalanche:
|
|
402
404
|
case Chain.Arbitrum:
|
|
405
|
+
case Chain.Arc:
|
|
403
406
|
case Chain.Berachain:
|
|
404
407
|
case Chain.Optimism:
|
|
405
408
|
case Chain.Polygon:
|
package/src/trezor/evmSigner.ts
CHANGED
|
@@ -123,14 +123,13 @@ export async function getEVMSigner({ chain, derivationPath, provider }: TrezorEV
|
|
|
123
123
|
if (!to) throw new SwapKitError({ errorKey: "wallet_missing_params", info: { to } });
|
|
124
124
|
if (!gasLimit) throw new SwapKitError({ errorKey: "wallet_missing_params", info: { gasLimit } });
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
// Check presence, not truthiness: a zero-wei tip is legitimate on chains with a negligible
|
|
127
|
+
// priority fee, such as Arc, where it used to be read as missing fee data.
|
|
128
|
+
const isEIP1559 = maxFeePerGas != null || maxPriorityFeePerGas != null;
|
|
127
129
|
|
|
128
130
|
if (isEIP1559 && !maxFeePerGas) {
|
|
129
131
|
throw new SwapKitError({ errorKey: "wallet_missing_params", info: { maxFeePerGas } });
|
|
130
132
|
}
|
|
131
|
-
if (isEIP1559 && !maxPriorityFeePerGas) {
|
|
132
|
-
throw new SwapKitError({ errorKey: "wallet_missing_params", info: { maxPriorityFeePerGas } });
|
|
133
|
-
}
|
|
134
133
|
if (!(isEIP1559 || gasPrice)) {
|
|
135
134
|
throw new SwapKitError({ errorKey: "wallet_missing_params", info: { gasPrice } });
|
|
136
135
|
}
|
package/src/trezor/index.ts
CHANGED
|
@@ -498,6 +498,7 @@ async function getTrezorWallet<T extends Chain>({
|
|
|
498
498
|
}) {
|
|
499
499
|
switch (chain) {
|
|
500
500
|
case Chain.Arbitrum:
|
|
501
|
+
case Chain.Arc:
|
|
501
502
|
case Chain.Aurora:
|
|
502
503
|
case Chain.Avalanche:
|
|
503
504
|
case Chain.Base:
|
|
@@ -1358,6 +1359,7 @@ export const trezorWallet = createWallet({
|
|
|
1358
1359
|
},
|
|
1359
1360
|
directSigningSupport: {
|
|
1360
1361
|
[Chain.Arbitrum]: true,
|
|
1362
|
+
[Chain.Arc]: true,
|
|
1361
1363
|
[Chain.Aurora]: true,
|
|
1362
1364
|
[Chain.Avalanche]: true,
|
|
1363
1365
|
[Chain.Base]: true,
|
|
@@ -1380,6 +1382,7 @@ export const trezorWallet = createWallet({
|
|
|
1380
1382
|
name: "connectTrezor",
|
|
1381
1383
|
supportedChains: [
|
|
1382
1384
|
Chain.Arbitrum,
|
|
1385
|
+
Chain.Arc,
|
|
1383
1386
|
Chain.Aurora,
|
|
1384
1387
|
Chain.Avalanche,
|
|
1385
1388
|
Chain.Base,
|
package/dist/chunk-qs60k0yv.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{d as Q}from"./chunk-n05bv2n5.js";import{ChainToChainId as b,derivationPathToString as $,SwapKitError as B,WalletOption as K}from"@swapkit/helpers";async function G({chain:_,derivationPath:f,provider:C}){let{AbstractSigner:H}=await import("ethers");class A extends H{address;chain;derivationPath;provider;constructor({chain:j,derivationPath:q,provider:J}){super(J);this.address="",this.chain=j,this.derivationPath=q,this.provider=J}getAddress=async()=>{if(!this.address){let q=await(await import("@trezor/connect-web")).default.ethereumGetAddress({path:$(this.derivationPath),showOnTrezor:!0});if(!q.success)throw new B({errorKey:"wallet_trezor_failed_to_get_address",info:{...q,chain:this.chain,derivationPath:this.derivationPath}});this.address=q.payload.address}return this.address};signMessage=async(j)=>{let J=await(await import("@trezor/connect-web")).default.ethereumSignMessage({message:j,path:$(this.derivationPath)});if(!J.success)throw new B({errorKey:"wallet_trezor_failed_to_sign_transaction",info:{...J,chain:this.chain,derivationPath:this.derivationPath,message:j}});return J.payload.signature};signTypedData=async(j,q,J,N)=>{let O=(await import("@trezor/connect-web")).default,{buildEIP712DomainType:V}=await import("@swapkit/toolboxes/evm"),{TypedDataEncoder:X}=await import("ethers"),{EIP712Domain:Y,...R}=q,W=N??X.from(R).primaryType,M=V(j),D={domain:j,message:J,primaryType:W,types:{EIP712Domain:M,...R}},U=await O.ethereumSignTypedData({data:D,metamask_v4_compat:!0,path:$(this.derivationPath)});if(!U.success)throw new B({errorKey:"wallet_trezor_failed_to_sign_transaction",info:{chain:this.chain,error:U.payload.error}});return U.payload.signature.startsWith("0x")?U.payload.signature:`0x${U.payload.signature}`};signTransaction=async({to:j,gasLimit:q,value:J,data:N,nonce:O,maxFeePerGas:V,maxPriorityFeePerGas:X,gasPrice:Y})=>{if(!j)throw new B({errorKey:"wallet_missing_params",info:{to:j}});if(!q)throw new B({errorKey:"wallet_missing_params",info:{gasLimit:q}});let R=V&&X;if(R&&!V)throw new B({errorKey:"wallet_missing_params",info:{maxFeePerGas:V}});if(R&&!X)throw new B({errorKey:"wallet_missing_params",info:{maxPriorityFeePerGas:X}});if(!(R||Y))throw new B({errorKey:"wallet_missing_params",info:{gasPrice:Y}});let W=(await import("@trezor/connect-web")).default,{toHexString:M}=await import("@swapkit/toolboxes/evm"),D=R?{maxFeePerGas:M(BigInt(V?.toString()||0)),maxPriorityFeePerGas:M(BigInt(X?.toString()||0))}:Y&&{gasPrice:M(BigInt(Y?.toString()||0))}||{gasPrice:"0x0"},U=M(BigInt(O||await this.provider.getTransactionCount(await this.getAddress(),"pending"))),I={chainId:Number.parseInt(b[this.chain],10),data:N?.toString()||"0x",gasLimit:M(BigInt(q?.toString()||0)),nonce:U,to:j.toString(),value:M(BigInt(J?.toString()||0)),...D},{success:L,payload:Z}=await W.ethereumSignTransaction({path:$(this.derivationPath),transaction:I});if(!L)throw new B({errorKey:"wallet_trezor_failed_to_sign_transaction",info:{...Z,chain:this.chain,derivationPath:this.derivationPath}});let k=Z.serializedTx?Z.serializedTx.startsWith("0x")?Z.serializedTx:`0x${Z.serializedTx}`:void 0;if(!k)throw new B({errorKey:"wallet_trezor_failed_to_sign_transaction",info:{chain:this.chain,derivationPath:this.derivationPath}});return k};connect=(j)=>{if(!j)throw new B({errorKey:"wallet_provider_not_found",info:{chain:this.chain,derivationPath:this.derivationPath,wallet:K.TREZOR}});return new A({chain:this.chain,derivationPath:this.derivationPath,provider:j})}}return new A({chain:_,derivationPath:f,provider:C})}export{G as getEVMSigner};
|
|
2
|
-
|
|
3
|
-
//# debugId=654BE0775B0291CD64756E2164756E21
|
|
4
|
-
//# sourceMappingURL=chunk-qs60k0yv.js.map
|