@cartridge/controller 0.10.0-alpha.1 → 0.10.1
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/.turbo/turbo-build$colon$deps.log +19 -19
- package/.turbo/turbo-build.log +17 -17
- package/dist/controller.d.ts +2 -2
- package/dist/index.js +2412 -1104
- package/dist/index.js.map +1 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.js +1 -1
- package/dist/node/index.js.map +1 -1
- package/dist/{provider-CKE81veU.js → provider-DSw1EyU9.js} +45 -44
- package/dist/provider-DSw1EyU9.js.map +1 -0
- package/dist/session.js +24 -24
- package/dist/session.js.map +1 -1
- package/dist/stats.html +1 -1
- package/dist/types.d.ts +20 -1
- package/dist/utils/solana/connection.d.ts +19 -0
- package/dist/utils/solana/index.d.ts +37 -0
- package/dist/utils/solana/spl-token.d.ts +6 -0
- package/dist/wallets/argent/index.d.ts +4 -0
- package/dist/wallets/base/index.d.ts +5 -18
- package/dist/wallets/braavos/index.d.ts +4 -0
- package/dist/wallets/ethereum-base.d.ts +29 -0
- package/dist/wallets/index.d.ts +2 -0
- package/dist/wallets/metamask/index.d.ts +5 -19
- package/dist/wallets/rabby/index.d.ts +5 -19
- package/dist/wallets/types.d.ts +1 -0
- package/package.json +5 -7
- package/src/__tests__/controllerDefaults.test.ts +5 -5
- package/src/__tests__/parseChainId.test.ts +6 -2
- package/src/controller.ts +8 -10
- package/src/types.ts +23 -1
- package/src/utils/solana/connection.ts +78 -0
- package/src/utils/solana/index.ts +143 -0
- package/src/utils/solana/spl-token.ts +66 -0
- package/src/wallets/argent/index.ts +36 -0
- package/src/wallets/base/index.ts +5 -303
- package/src/wallets/braavos/index.ts +36 -0
- package/src/wallets/ethereum-base.ts +446 -0
- package/src/wallets/index.ts +2 -0
- package/src/wallets/metamask/index.ts +5 -334
- package/src/wallets/phantom/index.ts +5 -1
- package/src/wallets/rabby/index.ts +5 -332
- package/src/wallets/types.ts +1 -0
- package/vite.config.js +0 -2
- package/dist/provider-CKE81veU.js.map +0 -1
|
@@ -1,337 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { createStore } from "mipd";
|
|
4
|
-
import {
|
|
5
|
-
ExternalPlatform,
|
|
6
|
-
ExternalWallet,
|
|
7
|
-
ExternalWalletResponse,
|
|
8
|
-
ExternalWalletType,
|
|
9
|
-
WalletAdapter,
|
|
10
|
-
} from "../types";
|
|
11
|
-
import { chainIdToPlatform } from "../platform";
|
|
1
|
+
import { ExternalWalletType } from "../types";
|
|
2
|
+
import { EthereumWalletBase } from "../ethereum-base";
|
|
12
3
|
|
|
13
|
-
export class MetaMaskWallet
|
|
4
|
+
export class MetaMaskWallet extends EthereumWalletBase {
|
|
14
5
|
readonly type: ExternalWalletType = "metamask";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
private MMSDK: MetaMaskSDK;
|
|
18
|
-
private store = createStore();
|
|
19
|
-
private account: string | undefined = undefined;
|
|
20
|
-
private connectedAccounts: string[] = [];
|
|
21
|
-
|
|
22
|
-
constructor() {
|
|
23
|
-
this.MMSDK = new MetaMaskSDK({
|
|
24
|
-
dappMetadata: {
|
|
25
|
-
name: "Cartridge Controller",
|
|
26
|
-
url: window.location.href,
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
if (this.isAvailable()) {
|
|
30
|
-
this.MMSDK.sdkInitPromise?.then(() => {
|
|
31
|
-
this.MMSDK.getProvider()
|
|
32
|
-
?.request({
|
|
33
|
-
method: "eth_accounts",
|
|
34
|
-
})
|
|
35
|
-
.then((accounts: any) => {
|
|
36
|
-
if (accounts && accounts.length > 0) {
|
|
37
|
-
this.account = getAddress(accounts[0]);
|
|
38
|
-
this.connectedAccounts = accounts.map(getAddress);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
this.MMSDK.getProvider()?.on("accountsChanged", (accounts: any) => {
|
|
42
|
-
if (Array.isArray(accounts)) {
|
|
43
|
-
if (accounts.length > 0) {
|
|
44
|
-
this.account = getAddress(accounts?.[0]);
|
|
45
|
-
this.connectedAccounts = accounts.map(getAddress);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
this.MMSDK.getProvider()?.on("chainChanged", (chainId: any) => {
|
|
50
|
-
this.platform = chainIdToPlatform(chainId);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const chainId = this.MMSDK.getProvider()?.chainId;
|
|
54
|
-
this.platform = chainId ? chainIdToPlatform(chainId) : undefined;
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
isAvailable(): boolean {
|
|
60
|
-
return (
|
|
61
|
-
typeof window !== "undefined" &&
|
|
62
|
-
this.store
|
|
63
|
-
.getProviders()
|
|
64
|
-
.some((provider) => provider.info.rdns === "io.metamask")
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
getInfo(): ExternalWallet {
|
|
69
|
-
const available = this.isAvailable();
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
type: this.type,
|
|
73
|
-
available,
|
|
74
|
-
version: available ? window.ethereum?.version || "Unknown" : undefined,
|
|
75
|
-
chainId: available ? window.ethereum?.chainId : undefined,
|
|
76
|
-
name: "MetaMask",
|
|
77
|
-
platform: this.platform,
|
|
78
|
-
connectedAccounts: this.connectedAccounts,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async connect(): Promise<ExternalWalletResponse<any>> {
|
|
83
|
-
if (this.account) {
|
|
84
|
-
return { success: true, wallet: this.type, account: this.account };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
if (!this.isAvailable()) {
|
|
89
|
-
throw new Error("MetaMask is not available");
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const accounts = await this.MMSDK.connect();
|
|
93
|
-
if (accounts && accounts.length > 0) {
|
|
94
|
-
this.account = getAddress(accounts[0]);
|
|
95
|
-
this.connectedAccounts = accounts.map((account: string) =>
|
|
96
|
-
getAddress(account),
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
return { success: true, wallet: this.type, account: this.account };
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
throw new Error("No accounts found");
|
|
103
|
-
} catch (error) {
|
|
104
|
-
console.error(`Error connecting to MetaMask:`, error);
|
|
105
|
-
return {
|
|
106
|
-
success: false,
|
|
107
|
-
wallet: this.type,
|
|
108
|
-
error: (error as Error).message || "Unknown error",
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
getConnectedAccounts(): string[] {
|
|
114
|
-
return this.connectedAccounts;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
async signTransaction(
|
|
118
|
-
transaction: any,
|
|
119
|
-
): Promise<ExternalWalletResponse<any>> {
|
|
120
|
-
try {
|
|
121
|
-
if (!this.isAvailable() || !this.account) {
|
|
122
|
-
throw new Error("MetaMask is not connected");
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const ethereum = this.MMSDK.getProvider();
|
|
126
|
-
if (!ethereum) {
|
|
127
|
-
throw new Error("MetaMask is not connected");
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const result = await ethereum.request({
|
|
131
|
-
method: "eth_sendTransaction",
|
|
132
|
-
params: [transaction],
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
return { success: true, wallet: this.type, result };
|
|
136
|
-
} catch (error) {
|
|
137
|
-
console.error(`Error signing transaction with MetaMask:`, error);
|
|
138
|
-
return {
|
|
139
|
-
success: false,
|
|
140
|
-
wallet: this.type,
|
|
141
|
-
error: (error as Error).message || "Unknown error",
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
async signMessage(
|
|
147
|
-
message: string,
|
|
148
|
-
address?: string,
|
|
149
|
-
): Promise<ExternalWalletResponse<any>> {
|
|
150
|
-
try {
|
|
151
|
-
if (!this.isAvailable() || !this.account) {
|
|
152
|
-
throw new Error("MetaMask is not connected");
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const result = await this.MMSDK.getProvider()?.request({
|
|
156
|
-
method: "personal_sign",
|
|
157
|
-
params: [address || this.account, message],
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
return { success: true, wallet: this.type, result };
|
|
161
|
-
} catch (error) {
|
|
162
|
-
console.error(`Error signing message with MetaMask:`, error);
|
|
163
|
-
return {
|
|
164
|
-
success: false,
|
|
165
|
-
wallet: this.type,
|
|
166
|
-
error: (error as Error).message || "Unknown error",
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async signTypedData(data: any): Promise<ExternalWalletResponse<any>> {
|
|
172
|
-
try {
|
|
173
|
-
if (!this.isAvailable() || !this.account) {
|
|
174
|
-
throw new Error("MetaMask is not connected");
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const ethereum = this.MMSDK.getProvider();
|
|
178
|
-
if (!ethereum) {
|
|
179
|
-
throw new Error("MetaMask is not connected");
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const result = await ethereum.request({
|
|
183
|
-
method: "eth_signTypedData_v4",
|
|
184
|
-
params: [this.account, JSON.stringify(data)],
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
return { success: true, wallet: this.type, result };
|
|
188
|
-
} catch (error) {
|
|
189
|
-
console.error(`Error signing typed data with MetaMask:`, error);
|
|
190
|
-
return {
|
|
191
|
-
success: false,
|
|
192
|
-
wallet: this.type,
|
|
193
|
-
error: (error as Error).message || "Unknown error",
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
async sendTransaction(txn: any): Promise<ExternalWalletResponse<any>> {
|
|
199
|
-
try {
|
|
200
|
-
if (!this.isAvailable() || !this.account) {
|
|
201
|
-
throw new Error("MetaMask is not connected");
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const provider = this.MMSDK.getProvider();
|
|
205
|
-
if (!provider) {
|
|
206
|
-
throw new Error("MetaMask is not connected");
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const result = await provider.request({
|
|
210
|
-
method: "eth_sendTransaction",
|
|
211
|
-
params: [txn],
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
return { success: true, wallet: this.type, result };
|
|
215
|
-
} catch (error) {
|
|
216
|
-
console.error(`Error sending transaction with MetaMask:`, error);
|
|
217
|
-
return {
|
|
218
|
-
success: false,
|
|
219
|
-
wallet: this.type,
|
|
220
|
-
error: (error as Error).message || "Unknown error",
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
async switchChain(chainId: string): Promise<boolean> {
|
|
226
|
-
try {
|
|
227
|
-
if (!this.isAvailable()) {
|
|
228
|
-
throw new Error("MetaMask is not available");
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const provider = this.MMSDK.getProvider();
|
|
232
|
-
if (!provider) {
|
|
233
|
-
throw new Error("MetaMask is not connected");
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
try {
|
|
237
|
-
await provider.request({
|
|
238
|
-
method: "wallet_switchEthereumChain",
|
|
239
|
-
params: [{ chainId }],
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
this.platform = chainIdToPlatform(chainId);
|
|
243
|
-
return true;
|
|
244
|
-
} catch (error) {
|
|
245
|
-
if ((error as any).code === 4902) {
|
|
246
|
-
console.warn("Chain not added to MetaMask");
|
|
247
|
-
}
|
|
248
|
-
throw error;
|
|
249
|
-
}
|
|
250
|
-
} catch (error) {
|
|
251
|
-
console.error(`Error switching chain for MetaMask:`, error);
|
|
252
|
-
return false;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
async getBalance(
|
|
257
|
-
tokenAddress?: string,
|
|
258
|
-
): Promise<ExternalWalletResponse<any>> {
|
|
259
|
-
try {
|
|
260
|
-
if (!this.isAvailable() || !this.account) {
|
|
261
|
-
throw new Error("MetaMask is not connected");
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (tokenAddress) {
|
|
265
|
-
return {
|
|
266
|
-
success: false,
|
|
267
|
-
wallet: this.type,
|
|
268
|
-
error: "Not implemented for ERC20",
|
|
269
|
-
};
|
|
270
|
-
} else {
|
|
271
|
-
const ethereum = this.MMSDK.getProvider();
|
|
272
|
-
if (!ethereum) {
|
|
273
|
-
throw new Error("MetaMask is not connected");
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
const balance = await ethereum.request({
|
|
277
|
-
method: "eth_getBalance",
|
|
278
|
-
params: [this.account, "latest"],
|
|
279
|
-
});
|
|
280
|
-
return { success: true, wallet: this.type, result: balance };
|
|
281
|
-
}
|
|
282
|
-
} catch (error) {
|
|
283
|
-
console.error(`Error getting balance from MetaMask:`, error);
|
|
284
|
-
return {
|
|
285
|
-
success: false,
|
|
286
|
-
wallet: this.type,
|
|
287
|
-
error: (error as Error).message || "Unknown error",
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
async waitForTransaction(
|
|
293
|
-
txHash: string,
|
|
294
|
-
timeoutMs: number = 60000,
|
|
295
|
-
): Promise<ExternalWalletResponse<any>> {
|
|
296
|
-
try {
|
|
297
|
-
if (!this.isAvailable()) {
|
|
298
|
-
throw new Error("MetaMask is not connected");
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const provider = this.MMSDK.getProvider();
|
|
302
|
-
if (!provider) {
|
|
303
|
-
throw new Error("MetaMask is not connected");
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const startTime = Date.now();
|
|
307
|
-
const pollInterval = 1000; // 1 second
|
|
308
|
-
|
|
309
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
310
|
-
const receipt = await provider.request({
|
|
311
|
-
method: "eth_getTransactionReceipt",
|
|
312
|
-
params: [txHash],
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
if (receipt) {
|
|
316
|
-
return {
|
|
317
|
-
success: true,
|
|
318
|
-
wallet: this.type,
|
|
319
|
-
result: receipt,
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Wait before polling again
|
|
324
|
-
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
throw new Error("Transaction confirmation timed out");
|
|
328
|
-
} catch (error) {
|
|
329
|
-
console.error(`Error waiting for transaction with MetaMask:`, error);
|
|
330
|
-
return {
|
|
331
|
-
success: false,
|
|
332
|
-
wallet: this.type,
|
|
333
|
-
error: (error as Error).message || "Unknown error",
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
}
|
|
6
|
+
readonly rdns = "io.metamask";
|
|
7
|
+
readonly displayName = "MetaMask";
|
|
337
8
|
}
|
|
@@ -1,335 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
ExternalPlatform,
|
|
5
|
-
ExternalWallet,
|
|
6
|
-
ExternalWalletResponse,
|
|
7
|
-
ExternalWalletType,
|
|
8
|
-
WalletAdapter,
|
|
9
|
-
} from "../types";
|
|
10
|
-
import { chainIdToPlatform } from "../platform";
|
|
1
|
+
import { ExternalWalletType } from "../types";
|
|
2
|
+
import { EthereumWalletBase } from "../ethereum-base";
|
|
11
3
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export class RabbyWallet implements WalletAdapter {
|
|
4
|
+
export class RabbyWallet extends EthereumWalletBase {
|
|
15
5
|
readonly type: ExternalWalletType = "rabby";
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
private account: string | undefined = undefined;
|
|
19
|
-
private store = createStore();
|
|
20
|
-
private provider: EIP6963ProviderDetail | undefined;
|
|
21
|
-
private connectedAccounts: string[] = [];
|
|
22
|
-
|
|
23
|
-
constructor() {
|
|
24
|
-
this.provider = this.store
|
|
25
|
-
.getProviders()
|
|
26
|
-
.find((provider) => provider.info.rdns === RABBY_RDNS);
|
|
27
|
-
this.provider?.provider
|
|
28
|
-
.request({
|
|
29
|
-
method: "eth_accounts",
|
|
30
|
-
})
|
|
31
|
-
.then((accounts) => {
|
|
32
|
-
this.connectedAccounts = accounts.map(getAddress);
|
|
33
|
-
if (accounts.length > 0) {
|
|
34
|
-
this.account = getAddress(accounts?.[0]);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
this.provider?.provider
|
|
39
|
-
.request({
|
|
40
|
-
method: "eth_chainId",
|
|
41
|
-
})
|
|
42
|
-
.then((chainId) => {
|
|
43
|
-
this.platform = chainIdToPlatform(chainId);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
this.provider?.provider?.on("chainChanged", (chainId: string) => {
|
|
47
|
-
this.platform = chainIdToPlatform(chainId);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
this.provider?.provider?.on("accountsChanged", (accounts: string[]) => {
|
|
51
|
-
if (accounts) {
|
|
52
|
-
// rabby doesn't allow multiple accounts to be connected at the same time
|
|
53
|
-
this.connectedAccounts = accounts.map((account) => getAddress(account));
|
|
54
|
-
this.account = getAddress(accounts?.[0]);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
isAvailable(): boolean {
|
|
60
|
-
return typeof window !== "undefined" && !!this.provider;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
getInfo(): ExternalWallet {
|
|
64
|
-
const available = this.isAvailable();
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
type: this.type,
|
|
68
|
-
available,
|
|
69
|
-
version: available ? window.ethereum?.version || "Unknown" : undefined,
|
|
70
|
-
chainId: available ? window.ethereum?.chainId : undefined,
|
|
71
|
-
name: "Rabby",
|
|
72
|
-
platform: this.platform,
|
|
73
|
-
connectedAccounts: this.connectedAccounts,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async connect(address?: string): Promise<ExternalWalletResponse<any>> {
|
|
78
|
-
if (address && this.connectedAccounts.includes(getAddress(address))) {
|
|
79
|
-
this.account = getAddress(address);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (this.account) {
|
|
83
|
-
return { success: true, wallet: this.type, account: this.account };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
try {
|
|
87
|
-
if (!this.isAvailable()) {
|
|
88
|
-
throw new Error("Rabby is not available");
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const accounts = await this.provider?.provider.request({
|
|
92
|
-
method: "eth_requestAccounts",
|
|
93
|
-
});
|
|
94
|
-
if (accounts && accounts.length > 0) {
|
|
95
|
-
this.account = getAddress(accounts[0]);
|
|
96
|
-
this.connectedAccounts = accounts.map(getAddress);
|
|
97
|
-
return { success: true, wallet: this.type, account: this.account };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
throw new Error("No accounts found");
|
|
101
|
-
} catch (error) {
|
|
102
|
-
console.error(`Error connecting to Rabby:`, error);
|
|
103
|
-
return {
|
|
104
|
-
success: false,
|
|
105
|
-
wallet: this.type,
|
|
106
|
-
error: (error as Error).message || "Unknown error",
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
getConnectedAccounts(): string[] {
|
|
112
|
-
return this.connectedAccounts;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
async signTransaction(
|
|
116
|
-
transaction: any,
|
|
117
|
-
): Promise<ExternalWalletResponse<any>> {
|
|
118
|
-
try {
|
|
119
|
-
if (!this.isAvailable() || !this.account) {
|
|
120
|
-
throw new Error("Rabby is not connected");
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const ethereum = this.provider?.provider;
|
|
124
|
-
if (!ethereum) {
|
|
125
|
-
throw new Error("Rabby is not connected");
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const result = await ethereum.request({
|
|
129
|
-
method: "eth_sendTransaction",
|
|
130
|
-
params: [transaction],
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
return { success: true, wallet: this.type, result };
|
|
134
|
-
} catch (error) {
|
|
135
|
-
console.error(`Error signing transaction with Rabby:`, error);
|
|
136
|
-
return {
|
|
137
|
-
success: false,
|
|
138
|
-
wallet: this.type,
|
|
139
|
-
error: (error as Error).message || "Unknown error",
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async signMessage(
|
|
145
|
-
message: `0x${string}`,
|
|
146
|
-
address?: string,
|
|
147
|
-
): Promise<ExternalWalletResponse<any>> {
|
|
148
|
-
try {
|
|
149
|
-
if (!this.isAvailable() || !this.account) {
|
|
150
|
-
throw new Error("Rabby is not connected");
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const result = await this.provider?.provider.request({
|
|
154
|
-
method: "personal_sign",
|
|
155
|
-
params: [address || this.account, message] as any,
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
return { success: true, wallet: this.type, result };
|
|
159
|
-
} catch (error) {
|
|
160
|
-
console.error(`Error signing message with Rabby:`, error);
|
|
161
|
-
return {
|
|
162
|
-
success: false,
|
|
163
|
-
wallet: this.type,
|
|
164
|
-
error: (error as Error).message || "Unknown error",
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async signTypedData(data: any): Promise<ExternalWalletResponse<any>> {
|
|
170
|
-
try {
|
|
171
|
-
if (!this.isAvailable() || !this.account) {
|
|
172
|
-
throw new Error("Rabby is not connected");
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const provider = this.provider?.provider;
|
|
176
|
-
if (!provider) {
|
|
177
|
-
throw new Error("Rabby is not connected");
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const result = await provider.request({
|
|
181
|
-
method: "eth_signTypedData_v4",
|
|
182
|
-
params: [this.account, JSON.stringify(data)] as any,
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
return { success: true, wallet: this.type, result };
|
|
186
|
-
} catch (error) {
|
|
187
|
-
console.error(`Error signing typed data with Rabby:`, error);
|
|
188
|
-
return {
|
|
189
|
-
success: false,
|
|
190
|
-
wallet: this.type,
|
|
191
|
-
error: (error as Error).message || "Unknown error",
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
async sendTransaction(txn: any): Promise<ExternalWalletResponse<any>> {
|
|
197
|
-
try {
|
|
198
|
-
if (!this.isAvailable() || !this.account) {
|
|
199
|
-
throw new Error("Rabby is not connected");
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const provider = this.provider?.provider;
|
|
203
|
-
if (!provider) {
|
|
204
|
-
throw new Error("Rabby is not connected");
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const result = await provider.request({
|
|
208
|
-
method: "eth_sendTransaction",
|
|
209
|
-
params: [txn],
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
return { success: true, wallet: this.type, result };
|
|
213
|
-
} catch (error) {
|
|
214
|
-
console.error(`Error sending transaction with Rabby:`, error);
|
|
215
|
-
return {
|
|
216
|
-
success: false,
|
|
217
|
-
wallet: this.type,
|
|
218
|
-
error: (error as Error).message || "Unknown error",
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
async switchChain(chainId: string): Promise<boolean> {
|
|
224
|
-
try {
|
|
225
|
-
if (!this.isAvailable()) {
|
|
226
|
-
throw new Error("Rabby is not available");
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const provider = this.provider?.provider;
|
|
230
|
-
if (!provider) {
|
|
231
|
-
throw new Error("Rabby is not connected");
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
try {
|
|
235
|
-
await provider.request({
|
|
236
|
-
method: "wallet_switchEthereumChain",
|
|
237
|
-
params: [{ chainId }],
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
this.platform = chainIdToPlatform(chainId);
|
|
241
|
-
return true;
|
|
242
|
-
} catch (error) {
|
|
243
|
-
if ((error as any).code === 4902) {
|
|
244
|
-
console.warn("Chain not added to Rabby");
|
|
245
|
-
}
|
|
246
|
-
throw error;
|
|
247
|
-
}
|
|
248
|
-
} catch (error) {
|
|
249
|
-
console.error(`Error switching chain for Rabby:`, error);
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
async getBalance(
|
|
255
|
-
tokenAddress?: string,
|
|
256
|
-
): Promise<ExternalWalletResponse<any>> {
|
|
257
|
-
try {
|
|
258
|
-
if (!this.isAvailable() || !this.account) {
|
|
259
|
-
throw new Error("Rabby is not connected");
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (tokenAddress) {
|
|
263
|
-
return {
|
|
264
|
-
success: false,
|
|
265
|
-
wallet: this.type,
|
|
266
|
-
error: "Not implemented for ERC20",
|
|
267
|
-
};
|
|
268
|
-
} else {
|
|
269
|
-
const provider = this.provider?.provider;
|
|
270
|
-
if (!provider) {
|
|
271
|
-
throw new Error("Rabby is not connected");
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
const balance = await provider.request({
|
|
275
|
-
method: "eth_getBalance",
|
|
276
|
-
params: [this.account, "latest"] as any,
|
|
277
|
-
});
|
|
278
|
-
return { success: true, wallet: this.type, result: balance };
|
|
279
|
-
}
|
|
280
|
-
} catch (error) {
|
|
281
|
-
console.error(`Error getting balance from Rabby:`, error);
|
|
282
|
-
return {
|
|
283
|
-
success: false,
|
|
284
|
-
wallet: this.type,
|
|
285
|
-
error: (error as Error).message || "Unknown error",
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
async waitForTransaction(
|
|
291
|
-
txHash: string,
|
|
292
|
-
timeoutMs: number = 60000,
|
|
293
|
-
): Promise<ExternalWalletResponse<any>> {
|
|
294
|
-
try {
|
|
295
|
-
if (!this.isAvailable()) {
|
|
296
|
-
throw new Error("Rabby is not connected");
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const provider = this.provider?.provider;
|
|
300
|
-
if (!provider) {
|
|
301
|
-
throw new Error("Rabby is not connected");
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
const startTime = Date.now();
|
|
305
|
-
const pollInterval = 1000; // 1 second
|
|
306
|
-
|
|
307
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
308
|
-
const receipt = await provider.request({
|
|
309
|
-
method: "eth_getTransactionReceipt",
|
|
310
|
-
params: [txHash as `0x${string}`],
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
if (receipt) {
|
|
314
|
-
return {
|
|
315
|
-
success: true,
|
|
316
|
-
wallet: this.type,
|
|
317
|
-
result: receipt,
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Wait before polling again
|
|
322
|
-
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
throw new Error("Transaction confirmation timed out");
|
|
326
|
-
} catch (error) {
|
|
327
|
-
console.error(`Error waiting for transaction with Rabby:`, error);
|
|
328
|
-
return {
|
|
329
|
-
success: false,
|
|
330
|
-
wallet: this.type,
|
|
331
|
-
error: (error as Error).message || "Unknown error",
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
}
|
|
6
|
+
readonly rdns = "io.rabby";
|
|
7
|
+
readonly displayName = "Rabby";
|
|
335
8
|
}
|
package/src/wallets/types.ts
CHANGED