@swapkit/wallets 3.0.0-beta.9 → 4.0.0-beta.39
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-0rgqnhd7.js +4 -0
- package/dist/{chunk-hxt2nqa8.js.map → chunk-0rgqnhd7.js.map} +3 -3
- package/dist/chunk-2aa1w78q.js +4 -0
- package/dist/chunk-2aa1w78q.js.map +10 -0
- package/dist/chunk-31bmhjxx.js +4 -0
- package/dist/chunk-31bmhjxx.js.map +10 -0
- package/dist/chunk-5mq0kpmy.js +5 -0
- package/dist/chunk-5mq0kpmy.js.map +10 -0
- package/dist/chunk-9sjqewve.js +5 -0
- package/dist/chunk-9sjqewve.js.map +10 -0
- package/dist/chunk-c11abmv4.js +5 -0
- package/dist/{chunk-6ndrbmhg.js.map → chunk-c11abmv4.js.map} +3 -3
- package/dist/chunk-cgt2fexr.js +4 -0
- package/dist/chunk-cgt2fexr.js.map +10 -0
- package/dist/chunk-etm8zfkk.js +4 -0
- package/dist/chunk-etm8zfkk.js.map +10 -0
- package/dist/chunk-hafkx3bw.js +4 -0
- package/dist/chunk-hafkx3bw.js.map +10 -0
- package/dist/chunk-qh8q7xr1.js +4 -0
- package/dist/chunk-qh8q7xr1.js.map +10 -0
- package/dist/{chunk-p1kdg37m.js → chunk-r308an05.js} +3 -2
- package/dist/{chunk-p1kdg37m.js.map → chunk-r308an05.js.map} +1 -1
- package/dist/chunk-sn6pgje5.js +4 -0
- package/dist/chunk-sn6pgje5.js.map +10 -0
- package/dist/chunk-vb4wtm2w.js +1 -0
- package/dist/chunk-wfattb4a.js +4 -0
- package/dist/chunk-wfattb4a.js.map +10 -0
- package/dist/src/bitget/index.cjs +3 -2
- package/dist/src/bitget/index.cjs.map +3 -3
- package/dist/src/bitget/index.js +3 -2
- package/dist/src/bitget/index.js.map +3 -3
- package/dist/src/coinbase/index.cjs +3 -2
- package/dist/src/coinbase/index.cjs.map +3 -3
- package/dist/src/coinbase/index.js +3 -2
- package/dist/src/coinbase/index.js.map +3 -3
- package/dist/src/cosmostation/index.cjs +4 -0
- package/dist/src/cosmostation/index.cjs.map +10 -0
- package/dist/src/cosmostation/index.js +4 -0
- package/dist/src/cosmostation/index.js.map +10 -0
- package/dist/src/ctrl/index.cjs +3 -2
- package/dist/src/ctrl/index.cjs.map +4 -4
- package/dist/src/ctrl/index.js +3 -2
- package/dist/src/ctrl/index.js.map +4 -4
- package/dist/src/evm-extensions/index.cjs +3 -2
- package/dist/src/evm-extensions/index.cjs.map +3 -3
- package/dist/src/evm-extensions/index.js +3 -2
- package/dist/src/evm-extensions/index.js.map +3 -3
- package/dist/src/exodus/index.cjs +3 -2
- package/dist/src/exodus/index.cjs.map +3 -3
- package/dist/src/exodus/index.js +3 -2
- package/dist/src/exodus/index.js.map +3 -3
- package/dist/src/index.cjs +1 -0
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/keepkey/index.cjs +3 -2
- package/dist/src/keepkey/index.cjs.map +9 -10
- package/dist/src/keepkey/index.js +3 -2
- package/dist/src/keepkey/index.js.map +9 -10
- package/dist/src/keepkey-bex/index.cjs +3 -2
- package/dist/src/keepkey-bex/index.cjs.map +4 -4
- package/dist/src/keepkey-bex/index.js +3 -2
- package/dist/src/keepkey-bex/index.js.map +4 -4
- package/dist/src/keplr/index.cjs +3 -2
- package/dist/src/keplr/index.cjs.map +3 -3
- package/dist/src/keplr/index.js +3 -2
- package/dist/src/keplr/index.js.map +3 -3
- package/dist/src/keystore/index.cjs +3 -2
- package/dist/src/keystore/index.cjs.map +4 -4
- package/dist/src/keystore/index.js +3 -2
- package/dist/src/keystore/index.js.map +4 -4
- package/dist/src/ledger/index.cjs +4 -3
- package/dist/src/ledger/index.cjs.map +17 -15
- package/dist/src/ledger/index.js +4 -3
- package/dist/src/ledger/index.js.map +17 -15
- package/dist/src/okx/index.cjs +3 -2
- package/dist/src/okx/index.cjs.map +4 -4
- package/dist/src/okx/index.js +3 -2
- package/dist/src/okx/index.js.map +4 -4
- package/dist/src/onekey/index.cjs +3 -2
- package/dist/src/onekey/index.cjs.map +3 -3
- package/dist/src/onekey/index.js +3 -2
- package/dist/src/onekey/index.js.map +3 -3
- package/dist/src/phantom/index.cjs +1 -0
- package/dist/src/phantom/index.js +3 -2
- package/dist/src/phantom/index.js.map +2 -2
- package/dist/src/polkadotjs/index.cjs +1 -0
- package/dist/src/polkadotjs/index.js +3 -2
- package/dist/src/polkadotjs/index.js.map +1 -1
- package/dist/src/radix/index.cjs +3 -2
- package/dist/src/radix/index.cjs.map +3 -3
- package/dist/src/radix/index.js +3 -2
- package/dist/src/radix/index.js.map +3 -3
- package/dist/src/talisman/index.cjs +1 -0
- package/dist/src/talisman/index.js +3 -2
- package/dist/src/talisman/index.js.map +1 -1
- package/dist/src/trezor/index.cjs +3 -2
- package/dist/src/trezor/index.cjs.map +3 -3
- package/dist/src/trezor/index.js +3 -2
- package/dist/src/trezor/index.js.map +3 -3
- package/dist/src/walletconnect/index.cjs +3 -2
- package/dist/src/walletconnect/index.cjs.map +6 -7
- package/dist/src/walletconnect/index.js +3 -2
- package/dist/src/walletconnect/index.js.map +6 -7
- package/package.json +73 -28
- package/src/bitget/helpers.ts +4 -4
- package/src/coinbase/signer.ts +4 -4
- package/src/cosmostation/index.ts +142 -0
- package/src/ctrl/index.ts +83 -0
- package/src/ctrl/walletHelpers.ts +98 -70
- package/src/evm-extensions/index.ts +4 -3
- package/src/exodus/index.ts +8 -9
- package/src/helpers/near-browser-provider.d.ts +286 -0
- package/src/helpers/near.ts +206 -0
- package/src/keepkey/chains/cosmos.ts +44 -50
- package/src/keepkey/chains/evm.ts +16 -8
- package/src/keepkey/chains/mayachain.ts +3 -2
- package/src/keepkey/chains/ripple.ts +118 -0
- package/src/keepkey/chains/thorchain.ts +3 -2
- package/src/keepkey/chains/utxo.ts +14 -3
- package/src/keepkey/coins.ts +11 -4
- package/src/keepkey/index.ts +20 -7
- package/src/keepkey-bex/index.ts +10 -14
- package/src/keepkey-bex/walletHelpers.ts +1 -1
- package/src/keplr/index.ts +4 -3
- package/src/keystore/helpers.ts +2 -4
- package/src/keystore/index.ts +2 -0
- package/src/ledger/clients/cosmos.ts +5 -4
- package/src/ledger/clients/evm.ts +7 -6
- package/src/ledger/clients/near.ts +86 -0
- package/src/ledger/clients/thorchain/helpers.ts +9 -4
- package/src/ledger/clients/thorchain/index.ts +3 -3
- package/src/ledger/clients/thorchain/lib.ts +3 -2
- package/src/ledger/clients/thorchain/utils.ts +20 -9
- package/src/ledger/clients/utxo.ts +3 -5
- package/src/ledger/clients/xrp.ts +66 -0
- package/src/ledger/cosmosTypes.ts +14 -10
- package/src/ledger/helpers/getLedgerAddress.ts +17 -3
- package/src/ledger/helpers/getLedgerClient.ts +63 -45
- package/src/ledger/helpers/getLedgerTransport.ts +5 -3
- package/src/ledger/index.ts +28 -7
- package/src/ledger/interfaces/CosmosLedgerInterface.ts +1 -2
- package/src/okx/helpers.ts +27 -9
- package/src/okx/index.ts +1 -0
- package/src/onekey/index.ts +3 -7
- package/src/radix/index.ts +4 -4
- package/src/trezor/evmSigner.ts +4 -4
- package/src/trezor/index.ts +14 -4
- package/src/types.ts +14 -0
- package/src/utils.ts +4 -0
- package/src/walletconnect/constants.ts +2 -0
- package/src/walletconnect/evmSigner.ts +8 -4
- package/src/walletconnect/helpers.ts +9 -2
- package/src/walletconnect/index.ts +134 -24
- package/dist/chunk-6ndrbmhg.js +0 -4
- package/dist/chunk-bhfpfqc3.js +0 -3
- package/dist/chunk-bhfpfqc3.js.map +0 -10
- package/dist/chunk-hxt2nqa8.js +0 -3
- package/dist/chunk-q81hzyra.js +0 -3
- package/dist/chunk-q81hzyra.js.map +0 -10
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
//TBD @towan to be moved somewhere else
|
|
2
|
+
import { SwapKitError } from "@swapkit/helpers";
|
|
3
|
+
import type { NearSigner } from "@swapkit/toolboxes/near";
|
|
4
|
+
import type { Account } from "near-api-js";
|
|
5
|
+
import {
|
|
6
|
+
type Action,
|
|
7
|
+
type Signature,
|
|
8
|
+
SignedTransaction,
|
|
9
|
+
type Transaction,
|
|
10
|
+
} from "near-api-js/lib/transaction";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* NEAR Browser Wallet Provider Interface
|
|
14
|
+
* Common interface implemented by browser extension wallets
|
|
15
|
+
*/
|
|
16
|
+
export interface NearBrowserWalletProvider {
|
|
17
|
+
// Connection methods
|
|
18
|
+
connect(params?: { contractId?: string; methodNames?: string[] }): Promise<
|
|
19
|
+
Account[] | { accountId: string }
|
|
20
|
+
>;
|
|
21
|
+
disconnect?(): Promise<void>;
|
|
22
|
+
signOut?(): Promise<void>; // Alternative to disconnect
|
|
23
|
+
|
|
24
|
+
// Account methods
|
|
25
|
+
getAccountId(): string | Promise<string>;
|
|
26
|
+
getAccounts?(): Promise<Account[]>;
|
|
27
|
+
isSignedIn(): boolean;
|
|
28
|
+
getPublicKey?(): Promise<string>;
|
|
29
|
+
|
|
30
|
+
// Signing methods
|
|
31
|
+
signMessage?(params: any): Promise<any>;
|
|
32
|
+
signAndSendTransaction(params: {
|
|
33
|
+
receiverId: string;
|
|
34
|
+
actions: Action[];
|
|
35
|
+
signerId?: string;
|
|
36
|
+
}): Promise<any>;
|
|
37
|
+
signAndSendTransactions?(params: {
|
|
38
|
+
transactions: Transaction[];
|
|
39
|
+
}): Promise<any[]>;
|
|
40
|
+
|
|
41
|
+
// Optional utility methods
|
|
42
|
+
request<T>(params: { method: string; params?: any }): Promise<T>;
|
|
43
|
+
verifyOwner?(params: {
|
|
44
|
+
message: string;
|
|
45
|
+
callbackUrl?: string;
|
|
46
|
+
}): Promise<any>;
|
|
47
|
+
getNetwork?(): Promise<{ networkId: string; nodeUrl: string }>;
|
|
48
|
+
|
|
49
|
+
// Event handlers (optional)
|
|
50
|
+
on?(event: string, handler: Function): void;
|
|
51
|
+
off?(event: string, handler: Function): void;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Helper to create a NEAR signer from browser extension providers
|
|
56
|
+
*/
|
|
57
|
+
export async function createNearSignerFromProvider(
|
|
58
|
+
provider: NearBrowserWalletProvider,
|
|
59
|
+
walletName: string,
|
|
60
|
+
) {
|
|
61
|
+
const isConnected = provider.isSignedIn ? provider.isSignedIn() : false;
|
|
62
|
+
if (!isConnected) {
|
|
63
|
+
await provider.connect({ contractId: "", methodNames: [] });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const signer = {
|
|
67
|
+
...provider,
|
|
68
|
+
async getPublicKey() {
|
|
69
|
+
// Most browser wallets expose public key through message signing
|
|
70
|
+
const { utils } = await import("near-api-js");
|
|
71
|
+
|
|
72
|
+
if (provider.getPublicKey) {
|
|
73
|
+
const pubKey = await provider.getPublicKey();
|
|
74
|
+
return utils.PublicKey.from(pubKey);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!provider.signMessage) {
|
|
78
|
+
throw new SwapKitError("wallet_ledger_method_not_supported", {
|
|
79
|
+
wallet: walletName,
|
|
80
|
+
method: "getPublicKey",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Most browser wallets don't expose public key directly
|
|
85
|
+
// Return a dummy public key
|
|
86
|
+
const { PublicKey } = await import("near-api-js/lib/utils");
|
|
87
|
+
// Create a dummy ed25519 public key
|
|
88
|
+
const dummyKeyData = Buffer.alloc(32);
|
|
89
|
+
const dummyKey = `ed25519:${Buffer.from(dummyKeyData).toString("base64")}`;
|
|
90
|
+
return PublicKey.from(dummyKey);
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
async signNep413Message(
|
|
94
|
+
message: string,
|
|
95
|
+
_accountId: string,
|
|
96
|
+
recipient: string,
|
|
97
|
+
nonce: Uint8Array,
|
|
98
|
+
callbackUrl?: string,
|
|
99
|
+
) {
|
|
100
|
+
if (!provider.signMessage) {
|
|
101
|
+
throw new SwapKitError("wallet_ledger_method_not_supported", {
|
|
102
|
+
wallet: walletName,
|
|
103
|
+
method: "signNep413Message",
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// We know signMessage exists because we checked above
|
|
108
|
+
const result = await (
|
|
109
|
+
provider as Required<Pick<NearBrowserWalletProvider, "signMessage">>
|
|
110
|
+
).signMessage({
|
|
111
|
+
message,
|
|
112
|
+
recipient,
|
|
113
|
+
nonce: Buffer.from(nonce),
|
|
114
|
+
callbackUrl,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
return result;
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
async signTransaction(transaction: Transaction) {
|
|
121
|
+
if (!provider.request) {
|
|
122
|
+
throw new SwapKitError("wallet_near_method_not_supported", {
|
|
123
|
+
wallet: walletName,
|
|
124
|
+
method: "request",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Browser wallets typically sign and send in one operation
|
|
129
|
+
// This is a limitation of browser wallet APIs
|
|
130
|
+
const result = await provider.request<{ signatures: Signature }>({
|
|
131
|
+
method: "near_signTransactions",
|
|
132
|
+
params: {
|
|
133
|
+
transactions: [transaction], // must be Array type
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const signedTransaction = new SignedTransaction({
|
|
138
|
+
transaction,
|
|
139
|
+
signature: result.signatures,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return [result.signatures.data, signedTransaction] as [
|
|
143
|
+
Uint8Array<ArrayBufferLike>,
|
|
144
|
+
SignedTransaction,
|
|
145
|
+
];
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
signDelegateAction(_delegateAction: any) {
|
|
149
|
+
// Most browser wallets don't support delegate actions yet
|
|
150
|
+
return Promise.reject(
|
|
151
|
+
new SwapKitError("wallet_ledger_method_not_supported", {
|
|
152
|
+
wallet: walletName,
|
|
153
|
+
method: "signDelegateAction",
|
|
154
|
+
}),
|
|
155
|
+
);
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
async getAddress() {
|
|
159
|
+
if (provider.getAccountId) {
|
|
160
|
+
return provider.getAccountId();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (provider.isSignedIn && !provider.isSignedIn()) {
|
|
164
|
+
// Try connect method for wallets that don't have requestSignIn
|
|
165
|
+
const result = await provider.connect();
|
|
166
|
+
if (Array.isArray(result) && result.length > 0 && result[0]) {
|
|
167
|
+
return typeof result[0] === "string" ? result[0] : result[0].accountId;
|
|
168
|
+
}
|
|
169
|
+
throw new SwapKitError("wallet_connection_rejected_by_user", {
|
|
170
|
+
wallet: walletName,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
throw new SwapKitError("wallet_connection_rejected_by_user", {
|
|
175
|
+
wallet: walletName,
|
|
176
|
+
});
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
return signer as NearSigner;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Detect if a wallet provider supports NEAR
|
|
185
|
+
*/
|
|
186
|
+
export function detectNearProvider(
|
|
187
|
+
window: any,
|
|
188
|
+
providerPath: string,
|
|
189
|
+
): NearBrowserWalletProvider | null {
|
|
190
|
+
const parts = providerPath.split(".");
|
|
191
|
+
let provider = window;
|
|
192
|
+
|
|
193
|
+
for (const part of parts) {
|
|
194
|
+
provider = provider?.[part];
|
|
195
|
+
if (!provider) return null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return provider;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get NEAR chain ID for WalletConnect
|
|
203
|
+
*/
|
|
204
|
+
export function getNearChainId(isTestnet: boolean): string {
|
|
205
|
+
return isTestnet ? "near:testnet" : "near:mainnet";
|
|
206
|
+
}
|
|
@@ -21,64 +21,58 @@ export const cosmosWalletMethods = async ({
|
|
|
21
21
|
getFeeRateFromThorswap,
|
|
22
22
|
createStargateClient,
|
|
23
23
|
} = await import("@swapkit/toolboxes/cosmos");
|
|
24
|
+
const derivationPathString = derivationPath
|
|
25
|
+
? derivationPathToString(derivationPath)
|
|
26
|
+
: `${DerivationPath.GAIA}/0`;
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
: `${DerivationPath.GAIA}/0`;
|
|
28
|
+
const { address: fromAddress } = (await sdk.address.cosmosGetAddress({
|
|
29
|
+
address_n: bip32ToAddressNList(derivationPathString),
|
|
30
|
+
})) as { address: string };
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
address_n: bip32ToAddressNList(derivationPathString),
|
|
32
|
-
})) as { address: string };
|
|
32
|
+
const toolbox = await getCosmosToolbox(Chain.Cosmos);
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
);
|
|
40
|
-
}
|
|
34
|
+
if (DEFAULT_COSMOS_FEE_MAINNET.amount[0]) {
|
|
35
|
+
DEFAULT_COSMOS_FEE_MAINNET.amount[0].amount = String(
|
|
36
|
+
await getFeeRateFromThorswap(ChainId.Cosmos, 500),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
// TODO support other cosmos assets
|
|
41
|
+
const transfer = async ({ assetValue, recipient, memo }: GenericTransferParams) => {
|
|
42
|
+
const amount = assetValue.getBaseValue("string");
|
|
43
|
+
const accountInfo = await toolbox.getAccount(fromAddress);
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
},
|
|
62
|
-
type: "cosmos-sdk/MsgSend",
|
|
45
|
+
const keepKeySignedTx = await sdk.cosmos.cosmosSignAmino({
|
|
46
|
+
signerAddress: fromAddress,
|
|
47
|
+
signDoc: {
|
|
48
|
+
fee: DEFAULT_COSMOS_FEE_MAINNET,
|
|
49
|
+
memo: memo || "",
|
|
50
|
+
sequence: accountInfo?.sequence.toString() ?? "",
|
|
51
|
+
chain_id: ChainId.Cosmos,
|
|
52
|
+
account_number: accountInfo?.accountNumber.toString() ?? "",
|
|
53
|
+
msgs: [
|
|
54
|
+
{
|
|
55
|
+
value: {
|
|
56
|
+
amount: [{ denom: "uatom", amount }],
|
|
57
|
+
to_address: recipient,
|
|
58
|
+
from_address: fromAddress,
|
|
63
59
|
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
type: "cosmos-sdk/MsgSend",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
});
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
const decodedBytes = atob(keepKeySignedTx.serialized);
|
|
67
|
+
const uint8Array = new Uint8Array(decodedBytes.length).map((_, i) =>
|
|
68
|
+
decodedBytes.charCodeAt(i),
|
|
69
|
+
);
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
const client = await createStargateClient(SKConfig.get("rpcUrls")[Chain.Cosmos]);
|
|
72
|
+
const response = await client.broadcastTx(uint8Array);
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
return response.transactionHash;
|
|
75
|
+
};
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
} catch (e) {
|
|
81
|
-
console.error(e);
|
|
82
|
-
throw e;
|
|
83
|
-
}
|
|
77
|
+
return { ...toolbox, transfer, address: fromAddress };
|
|
84
78
|
};
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ChainToChainId,
|
|
5
5
|
type DerivationPathArray,
|
|
6
6
|
NetworkDerivationPath,
|
|
7
|
+
SwapKitError,
|
|
7
8
|
derivationPathToString,
|
|
8
9
|
} from "@swapkit/helpers";
|
|
9
10
|
import type { JsonRpcProvider, Provider, TransactionRequest } from "ethers";
|
|
@@ -35,7 +36,7 @@ export class KeepKeySigner extends AbstractSigner {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
signTypedData(): Promise<string> {
|
|
38
|
-
throw new
|
|
39
|
+
throw new SwapKitError("wallet_keepkey_method_not_supported", { method: "signTypedData" });
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
getAddress = async () => {
|
|
@@ -62,14 +63,21 @@ export class KeepKeySigner extends AbstractSigner {
|
|
|
62
63
|
gasPrice,
|
|
63
64
|
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>
|
|
64
65
|
}: TransactionRequest) => {
|
|
65
|
-
if (!to)
|
|
66
|
-
|
|
67
|
-
if (!
|
|
66
|
+
if (!to)
|
|
67
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", { reason: "Missing to address" });
|
|
68
|
+
if (!gasLimit)
|
|
69
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", { reason: "Missing gasLimit" });
|
|
70
|
+
if (!data) throw new SwapKitError("wallet_keepkey_invalid_params", { reason: "Missing data" });
|
|
68
71
|
|
|
69
72
|
const isEIP1559 = !!((maxFeePerGas || maxPriorityFeePerGas) && !gasPrice);
|
|
70
|
-
if (isEIP1559 && !maxFeePerGas)
|
|
71
|
-
|
|
72
|
-
if (
|
|
73
|
+
if (isEIP1559 && !maxFeePerGas)
|
|
74
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", { reason: "Missing maxFeePerGas" });
|
|
75
|
+
if (isEIP1559 && !maxPriorityFeePerGas)
|
|
76
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", {
|
|
77
|
+
reason: "Missing maxPriorityFeePerGas",
|
|
78
|
+
});
|
|
79
|
+
if (!(isEIP1559 || gasPrice))
|
|
80
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", { reason: "Missing gasPrice" });
|
|
73
81
|
|
|
74
82
|
const { toHexString } = await import("@swapkit/toolboxes/evm");
|
|
75
83
|
|
|
@@ -100,7 +108,7 @@ export class KeepKeySigner extends AbstractSigner {
|
|
|
100
108
|
};
|
|
101
109
|
|
|
102
110
|
sendTransaction = async (tx: TransactionRequest): Promise<any> => {
|
|
103
|
-
if (!this.provider) throw new
|
|
111
|
+
if (!this.provider) throw new SwapKitError("wallet_keepkey_no_provider");
|
|
104
112
|
|
|
105
113
|
const signedTxHex = await this.signTransaction(tx);
|
|
106
114
|
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type DerivationPathArray,
|
|
8
8
|
type GenericTransferParams,
|
|
9
9
|
SKConfig,
|
|
10
|
+
SwapKitError,
|
|
10
11
|
derivationPathToString,
|
|
11
12
|
} from "@swapkit/helpers";
|
|
12
13
|
import type { ThorchainDepositParams } from "@swapkit/toolboxes/cosmos";
|
|
@@ -44,11 +45,11 @@ export const mayachainWalletMethods = async ({
|
|
|
44
45
|
sender,
|
|
45
46
|
memo,
|
|
46
47
|
}: SignTransactionParams) => {
|
|
47
|
-
const { makeSignDoc } = await import("@cosmjs/amino");
|
|
48
|
+
const { makeSignDoc } = (await import("@cosmjs/amino")).default;
|
|
48
49
|
const { getDenomWithChain } = await import("@swapkit/toolboxes/cosmos");
|
|
49
50
|
|
|
50
51
|
const account = await toolbox.getAccount(sender);
|
|
51
|
-
if (!account) throw new
|
|
52
|
+
if (!account) throw new SwapKitError("wallet_keepkey_account_not_found");
|
|
52
53
|
const { accountNumber, sequence = 0 } = account;
|
|
53
54
|
const amount = assetValue.getBaseValue("string");
|
|
54
55
|
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { KeepKeySdk } from "@keepkey/keepkey-sdk";
|
|
2
|
+
import {
|
|
3
|
+
Chain,
|
|
4
|
+
DerivationPath,
|
|
5
|
+
type DerivationPathArray,
|
|
6
|
+
type GenericTransferParams,
|
|
7
|
+
derivationPathToString,
|
|
8
|
+
} from "@swapkit/helpers";
|
|
9
|
+
import { bip32ToAddressNList } from "../coins";
|
|
10
|
+
|
|
11
|
+
import { getRippleToolbox } from "@swapkit/toolboxes/ripple";
|
|
12
|
+
|
|
13
|
+
export const rippleWalletMethods = async ({
|
|
14
|
+
sdk,
|
|
15
|
+
derivationPath,
|
|
16
|
+
}: {
|
|
17
|
+
sdk: KeepKeySdk;
|
|
18
|
+
derivationPath?: DerivationPathArray;
|
|
19
|
+
}) => {
|
|
20
|
+
// Derivation path handling (default to standard XRP 44'/144'/0'/0/0)
|
|
21
|
+
const derivationPathString = derivationPath
|
|
22
|
+
? derivationPathToString(derivationPath)
|
|
23
|
+
: `${DerivationPath[Chain.Ripple]}/0`;
|
|
24
|
+
|
|
25
|
+
// Fetch address from KeepKey
|
|
26
|
+
// @ts-ignore - keepkey-sdk typings may not yet include xrpGetAddress
|
|
27
|
+
const { address } = await (sdk as any).address.xrpGetAddress({
|
|
28
|
+
address_n: bip32ToAddressNList(derivationPathString),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Inject minimal signer so toolbox's address helpers work
|
|
32
|
+
const signer = {
|
|
33
|
+
getAddress: () => Promise.resolve(address),
|
|
34
|
+
signTransaction: () => {
|
|
35
|
+
throw new Error("signTransaction not supported via toolbox");
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const toolbox = await getRippleToolbox({ signer });
|
|
40
|
+
|
|
41
|
+
const transfer = async ({ recipient, assetValue, memo }: GenericTransferParams) => {
|
|
42
|
+
// Build XRPL Payment tx using toolbox helper
|
|
43
|
+
const tx = await toolbox.createTransaction({
|
|
44
|
+
assetValue,
|
|
45
|
+
recipient,
|
|
46
|
+
memo,
|
|
47
|
+
sender: address,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Convert toolbox Payment tx into KeepKey StdTx wrapper (KeepKey-specific format)
|
|
51
|
+
const stdTx = {
|
|
52
|
+
type: "auth/StdTx",
|
|
53
|
+
value: {
|
|
54
|
+
fee: {
|
|
55
|
+
amount: [
|
|
56
|
+
{
|
|
57
|
+
amount: "1000",
|
|
58
|
+
denom: "drop",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
gas: "28000",
|
|
62
|
+
},
|
|
63
|
+
memo: memo && memo.length > 0 ? memo : "",
|
|
64
|
+
msg: [
|
|
65
|
+
{
|
|
66
|
+
type: "ripple-sdk/MsgSend",
|
|
67
|
+
value: {
|
|
68
|
+
amount: [
|
|
69
|
+
{
|
|
70
|
+
amount: tx.Amount,
|
|
71
|
+
denom: "drop",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
from_address: address,
|
|
75
|
+
to_address: recipient,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
signatures: null,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const unsignedTx = {
|
|
84
|
+
addressNList: bip32ToAddressNList(derivationPathString),
|
|
85
|
+
tx: stdTx,
|
|
86
|
+
flags: tx.Flags === 0 ? undefined : tx.Flags,
|
|
87
|
+
lastLedgerSequence: tx.LastLedgerSequence?.toString(),
|
|
88
|
+
sequence: (tx.Sequence ?? 0).toString(),
|
|
89
|
+
payment: {
|
|
90
|
+
amount: tx.Amount,
|
|
91
|
+
destination: tx.Destination,
|
|
92
|
+
destinationTag: (tx.DestinationTag ?? "0").toString(),
|
|
93
|
+
},
|
|
94
|
+
} as any;
|
|
95
|
+
|
|
96
|
+
// Sign with KeepKey
|
|
97
|
+
// @ts-ignore - typings missing
|
|
98
|
+
const responseSign = JSON.parse(await (sdk as any).xrp.xrpSignTransaction(unsignedTx));
|
|
99
|
+
|
|
100
|
+
// keepkey-sdk may return either { tx_blob } or StdTx with Base64 serializedTx
|
|
101
|
+
const txBlob: string | undefined =
|
|
102
|
+
(responseSign as any).tx_blob ?? (responseSign as any).value?.signatures?.[0]?.serializedTx;
|
|
103
|
+
if (!txBlob) throw new Error("KeepKey XRP sign failed");
|
|
104
|
+
|
|
105
|
+
const buffer = Buffer.from(txBlob, "base64");
|
|
106
|
+
const txBlobHex = buffer.toString("hex");
|
|
107
|
+
|
|
108
|
+
// Broadcast signed tx via toolbox
|
|
109
|
+
return toolbox.broadcastTransaction(txBlobHex);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
...toolbox,
|
|
114
|
+
address,
|
|
115
|
+
getAddress: () => address,
|
|
116
|
+
transfer,
|
|
117
|
+
};
|
|
118
|
+
};
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
type DerivationPathArray,
|
|
12
12
|
type GenericTransferParams,
|
|
13
13
|
SKConfig,
|
|
14
|
+
SwapKitError,
|
|
14
15
|
derivationPathToString,
|
|
15
16
|
} from "@swapkit/helpers";
|
|
16
17
|
import type { ThorchainDepositParams } from "@swapkit/toolboxes/cosmos";
|
|
@@ -31,7 +32,7 @@ export const thorchainWalletMethods = async ({
|
|
|
31
32
|
sdk: KeepKeySdk;
|
|
32
33
|
derivationPath?: DerivationPathArray;
|
|
33
34
|
}) => {
|
|
34
|
-
const { makeSignDoc } = await import("@cosmjs/amino");
|
|
35
|
+
const { makeSignDoc } = (await import("@cosmjs/amino")).default;
|
|
35
36
|
const { buildAminoMsg, getDefaultChainFee, createStargateClient, getCosmosToolbox } =
|
|
36
37
|
await import("@swapkit/toolboxes/cosmos");
|
|
37
38
|
|
|
@@ -51,7 +52,7 @@ export const thorchainWalletMethods = async ({
|
|
|
51
52
|
memo,
|
|
52
53
|
}: SignTransactionParams) => {
|
|
53
54
|
const account = await toolbox.getAccount(sender);
|
|
54
|
-
if (!account) throw new
|
|
55
|
+
if (!account) throw new SwapKitError("wallet_keepkey_account_not_found");
|
|
55
56
|
const { accountNumber, sequence = 0 } = account;
|
|
56
57
|
|
|
57
58
|
const isTransfer = recipient && recipient !== "";
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
type DerivationPathArray,
|
|
6
6
|
FeeOption,
|
|
7
7
|
type GenericTransferParams,
|
|
8
|
+
SwapKitError,
|
|
8
9
|
type UTXOChain,
|
|
9
10
|
derivationPathToString,
|
|
10
11
|
} from "@swapkit/helpers";
|
|
@@ -26,7 +27,11 @@ export const utxoWalletMethods = async ({
|
|
|
26
27
|
sdk,
|
|
27
28
|
chain,
|
|
28
29
|
derivationPath,
|
|
29
|
-
}: {
|
|
30
|
+
}: {
|
|
31
|
+
sdk: KeepKeySdk;
|
|
32
|
+
chain: Exclude<UTXOChain, Chain.Zcash>;
|
|
33
|
+
derivationPath?: DerivationPathArray;
|
|
34
|
+
}) => {
|
|
30
35
|
const { getUtxoToolbox } = await import("@swapkit/toolboxes/utxo");
|
|
31
36
|
// This might not work for BCH
|
|
32
37
|
const toolbox = await getUtxoToolbox(chain);
|
|
@@ -101,8 +106,14 @@ export const utxoWalletMethods = async ({
|
|
|
101
106
|
memo,
|
|
102
107
|
...rest
|
|
103
108
|
}: GenericTransferParams) => {
|
|
104
|
-
if (!walletAddress)
|
|
105
|
-
|
|
109
|
+
if (!walletAddress)
|
|
110
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", {
|
|
111
|
+
reason: "From address must be provided",
|
|
112
|
+
});
|
|
113
|
+
if (!recipient)
|
|
114
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", {
|
|
115
|
+
reason: "Recipient address must be provided",
|
|
116
|
+
});
|
|
106
117
|
|
|
107
118
|
const createTxMethod =
|
|
108
119
|
chain === Chain.BitcoinCash
|
package/src/keepkey/coins.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
KeepKey Specific bip32 path conventions
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { SwapKitError } from "@swapkit/helpers";
|
|
6
|
+
|
|
5
7
|
const HARDENED = 0x80000000;
|
|
6
8
|
|
|
7
9
|
export enum ChainToKeepKeyName {
|
|
@@ -10,6 +12,7 @@ export enum ChainToKeepKeyName {
|
|
|
10
12
|
DOGE = "Dogecoin",
|
|
11
13
|
LTC = "Litecoin",
|
|
12
14
|
DASH = "Dash",
|
|
15
|
+
XRP = "Ripple",
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
export function addressNListToBIP32(address: number[]) {
|
|
@@ -27,7 +30,9 @@ export function bip32ToAddressNList(initPath: string): number[] {
|
|
|
27
30
|
let path = initPath;
|
|
28
31
|
|
|
29
32
|
if (!bip32Like(path)) {
|
|
30
|
-
throw new
|
|
33
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", {
|
|
34
|
+
reason: `Not a bip32 path: '${path}'`,
|
|
35
|
+
});
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
if (/^m\//i.test(path)) {
|
|
@@ -44,18 +49,20 @@ export function bip32ToAddressNList(initPath: string): number[] {
|
|
|
44
49
|
const segment = segments[i];
|
|
45
50
|
if (segment) {
|
|
46
51
|
const tmp = /(\d+)([hH']?)/.exec(segment);
|
|
47
|
-
if (tmp === null)
|
|
52
|
+
if (tmp === null)
|
|
53
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", { reason: "Invalid input" });
|
|
48
54
|
|
|
49
55
|
const [, num = "", modifier = ""] = tmp;
|
|
50
56
|
|
|
51
57
|
ret[i] = Number.parseInt(num, 10);
|
|
52
58
|
|
|
53
|
-
if (ret[i] >= HARDENED)
|
|
59
|
+
if (ret[i] >= HARDENED)
|
|
60
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", { reason: "Invalid child index" });
|
|
54
61
|
|
|
55
62
|
if (modifier === "h" || modifier === "H" || modifier === "'") {
|
|
56
63
|
ret[i] += HARDENED;
|
|
57
64
|
} else if (modifier.length > 0) {
|
|
58
|
-
throw new
|
|
65
|
+
throw new SwapKitError("wallet_keepkey_invalid_params", { reason: "Invalid modifier" });
|
|
59
66
|
}
|
|
60
67
|
}
|
|
61
68
|
}
|