@megaeth-labs/wallet-sdk 0.1.9-beta.1 → 0.1.9
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/README.md +27 -395
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,410 +1,42 @@
|
|
|
1
|
-
#
|
|
1
|
+
# MegaETH Wallet SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Distributed to partners to work with the MegaETH wallet. Is responsible for loading the wallet inside an iFrame and
|
|
4
|
+
communicating with it.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
## Setup
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
Install dependencies: `pnpm i`
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
Link package locally so other packages can use it: `pnpm dev:link`
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
Sets up the iFrame-based wallet. Resolves when the wallet is ready.
|
|
12
|
+
Auto build during dev: `pnpm dev`
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
import { mega } from '@megaeth-labs/wallet-sdk';
|
|
16
|
-
|
|
17
|
-
await mega.initialise({
|
|
18
|
-
network: 'mainnet', // or 'testnet'
|
|
19
|
-
logging: 'error', // Optional: 'debug' | 'info' | 'warn' | 'error'
|
|
20
|
-
debug: false, // Optional: Enable internal verbose debug logging
|
|
21
|
-
sponsorUrl: 'https://your-sponsor-url.com', // Optional: Custom sponsor URL - see Sponsoring
|
|
22
|
-
sponsorMode: 'app-only', // Optional: 'everything' | 'app-only' | 'explicit'
|
|
23
|
-
sponsorToken: 'native', // Optional: 'native' | 'usdm'
|
|
24
|
-
});
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Connection Management
|
|
28
|
-
|
|
29
|
-
### Connect Wallet
|
|
30
|
-
Shows the connection UI and resolves when the user connects or cancels.
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
const { status, address } = await mega.connect();
|
|
34
|
-
|
|
35
|
-
if (status === 'connected') {
|
|
36
|
-
console.log('Wallet connected:', address);
|
|
37
|
-
}
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### Check Status
|
|
41
|
-
Get the current connection status without prompting the user.
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
const { status, address } = await mega.status();
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Disconnect
|
|
48
|
-
Disconnect the current wallet session.
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
const result = await mega.disconnect();
|
|
52
|
-
console.log('Disconnected:', result.status);
|
|
53
|
-
```
|
|
14
|
+
Build once: `pnpm build`
|
|
54
15
|
|
|
55
|
-
##
|
|
16
|
+
## How It Works
|
|
56
17
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
const auth = await mega.authenticate();
|
|
18
|
+
The bulk of the logic can be found in the `src/wallet.ts` file. It handles the initialization of the wallet,
|
|
19
|
+
communication with the iframe, and event handling. It exposes a object `mega` which contains all the methods to initialise and communicate with the iFrame.
|
|
62
20
|
|
|
63
|
-
|
|
64
|
-
const response = await fetch(
|
|
65
|
-
`https://wallet-api.megaeth.com/v1/partner-auth/verify?origin=${window.location.host}&jwt=${auth.jwt}`
|
|
66
|
-
);
|
|
67
|
-
const { walletAddress } = await response.json();
|
|
68
|
-
}
|
|
69
|
-
```
|
|
21
|
+
Communication is handled using the `penpal` library which ensures that messages are sent and received securely and reliably between the parent window and the iframe.
|
|
70
22
|
|
|
71
|
-
|
|
23
|
+
**Initialisation Flow**
|
|
24
|
+
Calling `mega.initialise()` triggers the following steps:
|
|
25
|
+
1. iFrame is created and loaded
|
|
26
|
+
2. Penpal is initialised to handle communication with the iFrame
|
|
27
|
+
3. A method `ready` is exposed to the iFrame
|
|
28
|
+
4. The iFrame loads and checks wallet status and then calls `ready` in the parent window
|
|
72
29
|
|
|
73
|
-
|
|
74
|
-
|
|
30
|
+
**Methods**
|
|
31
|
+
Each of the available methods can be found in the `src/outbound-methods` folder and follow the same pattern:
|
|
32
|
+
1. Validate the request
|
|
33
|
+
2. Use `Remote.remote.methodName` to call the method in the iFrame
|
|
34
|
+
3. The promise remains open until the iFrame responds
|
|
35
|
+
4. Result is returned
|
|
75
36
|
|
|
37
|
+
For example:
|
|
76
38
|
```typescript
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const result = await mega.transfer({
|
|
80
|
-
type: 'native',
|
|
81
|
-
to: '0xRecipientAddress',
|
|
82
|
-
amount: parseEther('0.1').toString(),
|
|
83
|
-
sponsor: false, // Optional: Use sponsored transactions when sponsor mode is explict
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
if (result.status === 'approved') {
|
|
87
|
-
console.log('Transaction hash:', result.receipt.hash);
|
|
88
|
-
}
|
|
39
|
+
const {signature, status} = await mega.signMessage('Hello World');
|
|
89
40
|
```
|
|
90
41
|
|
|
91
|
-
|
|
92
|
-
Transfer ERC20 tokens.
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
import { parseUnits } from 'viem';
|
|
96
|
-
|
|
97
|
-
const result = await mega.transfer({
|
|
98
|
-
type: 'erc20',
|
|
99
|
-
to: '0xRecipientAddress',
|
|
100
|
-
amount: parseUnits('100', 18).toString(), // 100 tokens with 18 decimals
|
|
101
|
-
contractAddress: '0xTokenContractAddress',
|
|
102
|
-
});
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### ERC721 NFT Transfer
|
|
106
|
-
Transfer an ERC721 NFT.
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
const result = await mega.transfer({
|
|
110
|
-
type: 'erc721',
|
|
111
|
-
to: '0xRecipientAddress',
|
|
112
|
-
contractAddress: '0xNFTContractAddress',
|
|
113
|
-
tokenId: 1234,
|
|
114
|
-
amount: '0',
|
|
115
|
-
});
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### ERC1155 Token Transfer
|
|
119
|
-
Transfer ERC1155 tokens.
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
const result = await mega.transfer({
|
|
123
|
-
type: 'erc1155',
|
|
124
|
-
to: '0xRecipientAddress',
|
|
125
|
-
contractAddress: '0xTokenContractAddress',
|
|
126
|
-
tokenId: 1,
|
|
127
|
-
amount: '5', // Number of tokens to transfer
|
|
128
|
-
});
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
## Smart Contract Interactions
|
|
132
|
-
|
|
133
|
-
### Call Contract Method
|
|
134
|
-
Execute a contract method with user approval.
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
const result = await mega.callContract({
|
|
138
|
-
address: '0xContractAddress',
|
|
139
|
-
abi: contractABI,
|
|
140
|
-
functionName: 'mint',
|
|
141
|
-
args: [parseEther('1')],
|
|
142
|
-
value: parseEther('0.1'), // Optional: ETH value to send
|
|
143
|
-
sponsor: false, // Optional: Use sponsored transactions when sponsor mode is explict
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
if (result.status === 'approved') {
|
|
147
|
-
console.log('Transaction hash:', result.receipt.hash);
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Silent Contract Call (Session Keys)
|
|
152
|
-
Execute a contract method silently using session key permissions (no user approval required).
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
const result = await mega.callContract({
|
|
156
|
-
address: '0xContractAddress',
|
|
157
|
-
abi: contractABI,
|
|
158
|
-
functionName: 'claim',
|
|
159
|
-
args: [],
|
|
160
|
-
silent: true, // Uses session key with pre-approved permissions
|
|
161
|
-
});
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Batch Contract Calls
|
|
165
|
-
Execute multiple contract calls in a single transaction.
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
const result = await mega.callContract([
|
|
169
|
-
{
|
|
170
|
-
address: '0xContract1',
|
|
171
|
-
abi: abi1,
|
|
172
|
-
functionName: 'approve',
|
|
173
|
-
args: ['0xSpender', parseEther('100')],
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
address: '0xContract2',
|
|
177
|
-
abi: abi2,
|
|
178
|
-
functionName: 'swap',
|
|
179
|
-
args: [parseEther('100')],
|
|
180
|
-
},
|
|
181
|
-
]);
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### Call Contract with Raw Data
|
|
185
|
-
Execute a contract call using raw calldata instead of ABI.
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
const result = await mega.callContract({
|
|
189
|
-
address: '0xContractAddress',
|
|
190
|
-
data: '0x...' as `0x${string}`,
|
|
191
|
-
value: parseEther('0.1'),
|
|
192
|
-
});
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### Read from Contract (No Gas)
|
|
196
|
-
Read data from a contract without creating a transaction.
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
const balance = await mega.getFromContract<bigint>({
|
|
200
|
-
address: '0xTokenContract',
|
|
201
|
-
abi: erc20ABI,
|
|
202
|
-
functionName: 'balanceOf',
|
|
203
|
-
args: ['0xUserAddress'],
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
console.log('Balance:', balance.toString());
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
## Session Keys & Permissions
|
|
210
|
-
|
|
211
|
-
### Grant Permissions
|
|
212
|
-
Grant session key permissions for silent transactions. Users approve once, then your app can execute permitted transactions without additional prompts.
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
import { parseEther } from 'viem';
|
|
216
|
-
|
|
217
|
-
const result = await mega.grantPermissions({
|
|
218
|
-
permissions: {
|
|
219
|
-
expiry: 86400, // Expiry in seconds (24 hours)
|
|
220
|
-
feeToken: {
|
|
221
|
-
limit: parseEther('0.01').toString(), // Max fee allowed per transaction
|
|
222
|
-
symbol: 'ETH', // Optional: Fee token symbol
|
|
223
|
-
},
|
|
224
|
-
permissions: {
|
|
225
|
-
// Specific contract calls allowed
|
|
226
|
-
calls: [
|
|
227
|
-
{
|
|
228
|
-
to: '0xContractAddress',
|
|
229
|
-
signature: 'mint(uint256)', // Function signature
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
to: '0xAnotherContract',
|
|
233
|
-
signature: 'claim()',
|
|
234
|
-
},
|
|
235
|
-
],
|
|
236
|
-
// Spending limits for tokens
|
|
237
|
-
spend: [
|
|
238
|
-
{
|
|
239
|
-
limit: parseEther('100'), // 100 ETH
|
|
240
|
-
period: 'day', // 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'
|
|
241
|
-
token: undefined, // undefined for native ETH
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
limit: parseEther('1000'), // 1000 tokens
|
|
245
|
-
period: 'week',
|
|
246
|
-
token: '0xTokenAddress' as `0x${string}`,
|
|
247
|
-
},
|
|
248
|
-
],
|
|
249
|
-
},
|
|
250
|
-
},
|
|
251
|
-
externalAddress: '0xYourAppAddress', // Optional: External address for permissions if sending from another wallet (e.g. from your API)
|
|
252
|
-
sponsor: false, // Optional: Sponsor the permission grant transaction when sponsor mode is explicit
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
if (result.status === 'approved') {
|
|
256
|
-
console.log('Permissions granted');
|
|
257
|
-
}
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
### Get Current Permissions
|
|
261
|
-
Check what permissions are currently active for an address.
|
|
262
|
-
|
|
263
|
-
```typescript
|
|
264
|
-
const perms = await mega.getPermissions('0xUserAddress'); // Optional: address parameter
|
|
265
|
-
|
|
266
|
-
if (perms?.permissions) {
|
|
267
|
-
console.log('Expiry:', new Date(perms.permissions.expiry * 1000));
|
|
268
|
-
console.log('Allowed calls:', perms.permissions.permissions.calls);
|
|
269
|
-
console.log('Spending limits:', perms.permissions.permissions.spend);
|
|
270
|
-
}
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
### Revoke Permissions
|
|
274
|
-
Revoke all active session key permissions.
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
await mega.revokePermissions();
|
|
278
|
-
console.log('All permissions revoked');
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
## Message Signing
|
|
282
|
-
|
|
283
|
-
### Sign Message
|
|
284
|
-
Request the user to sign a message.
|
|
285
|
-
|
|
286
|
-
```typescript
|
|
287
|
-
const result = await mega.signMessage('Hello, World!');
|
|
288
|
-
|
|
289
|
-
if (result.status === 'success' && result.signature) {
|
|
290
|
-
console.log('Signature:', result.signature);
|
|
291
|
-
}
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
### Sign Structured Data (EIP-712)
|
|
295
|
-
Sign typed structured data.
|
|
296
|
-
|
|
297
|
-
```typescript
|
|
298
|
-
const domain = {
|
|
299
|
-
name: 'MyApp',
|
|
300
|
-
version: '1',
|
|
301
|
-
chainId: 1,
|
|
302
|
-
verifyingContract: '0xContract',
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
const types = {
|
|
306
|
-
Person: [
|
|
307
|
-
{ name: 'name', type: 'string' },
|
|
308
|
-
{ name: 'wallet', type: 'address' },
|
|
309
|
-
],
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
const value = {
|
|
313
|
-
name: 'Alice',
|
|
314
|
-
wallet: '0x...',
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
const result = await mega.signData({
|
|
318
|
-
data: { domain, types, value },
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
if (result.status === 'success' && result.signature) {
|
|
322
|
-
console.log('Signature:', result.signature);
|
|
323
|
-
}
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### Verifying Messages
|
|
327
|
-
For SIWE messages, the `@megaeth-labss/wallet-server-verify` package can be used to verify the signature.
|
|
328
|
-
|
|
329
|
-
For other messages or for more control, the following code can be used:
|
|
330
|
-
|
|
331
|
-
```typescript
|
|
332
|
-
import { PersonalMessage } from 'ox';
|
|
333
|
-
import { Porto, RelayActions } from 'porto';
|
|
334
|
-
import { RelayClient } from 'porto/viem';
|
|
335
|
-
import { http, toBytes } from 'viem';
|
|
336
|
-
import { megaeth, megaethTestnet } from 'viem/chains';
|
|
337
|
-
|
|
338
|
-
const message = 'Hello';
|
|
339
|
-
const address = '0x...';
|
|
340
|
-
const signature = '0x...';
|
|
341
|
-
const chainId = 4326;
|
|
342
|
-
|
|
343
|
-
const porto = Porto.create({
|
|
344
|
-
relay: http('https://wallet-relay.megaeth.com'),
|
|
345
|
-
chains: [megaeth, megaethTestnet],
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
const client = RelayClient.fromPorto(porto, {
|
|
349
|
-
chainId
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
const result = await RelayActions.verifySignature(client, {
|
|
353
|
-
address,
|
|
354
|
-
digest: PersonalMessage.getSignPayload(toBytes(message)),
|
|
355
|
-
signature
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
if(!result.valid) {
|
|
359
|
-
throw new Error('Invalid Signature');
|
|
360
|
-
}
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
## Wallet Information
|
|
364
|
-
|
|
365
|
-
### Get Token Balances
|
|
366
|
-
Retrieve the user's token balances.
|
|
367
|
-
|
|
368
|
-
```typescript
|
|
369
|
-
// Get all tokens
|
|
370
|
-
const allBalances = await mega.balances({});
|
|
371
|
-
|
|
372
|
-
// Get specific tokens
|
|
373
|
-
const specificBalances = await mega.balances({
|
|
374
|
-
tokens: ['0xTokenAddress1', '0xTokenAddress2'],
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
specificBalances.forEach(token => {
|
|
378
|
-
console.log(`${token.symbol}: ${token.displayBalance}`);
|
|
379
|
-
console.log(`USD Value: $${token.usdBalance}`);
|
|
380
|
-
});
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
### Open Wallet UI
|
|
384
|
-
Open the wallet interface for the user.
|
|
385
|
-
|
|
386
|
-
```typescript
|
|
387
|
-
await mega.open();
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### Deposit Funds
|
|
391
|
-
Show the deposit UI to help users fund their wallet.
|
|
392
|
-
|
|
393
|
-
```typescript
|
|
394
|
-
await mega.deposit();
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
## Event Handling
|
|
398
|
-
|
|
399
|
-
Listen to wallet events for real-time updates.
|
|
400
|
-
|
|
401
|
-
```typescript
|
|
402
|
-
// Listen for status changes
|
|
403
|
-
mega.events.on('statusChange', ({ status, address }) => {
|
|
404
|
-
console.log('Status changed:', status, address);
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
// Stop listening
|
|
408
|
-
const unsubscribe = mega.events.on('statusChange', handler);
|
|
409
|
-
unsubscribe(); // Call to remove listener
|
|
410
|
-
```
|
|
42
|
+
All request and return types are defined in the `src/types.ts` file.
|