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