@worldcoin/minikit-js 1.11.0 → 2.0.0-dev.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.
Files changed (39) hide show
  1. package/README.md +107 -0
  2. package/build/address-book.cjs +81 -0
  3. package/build/address-book.d.cts +3 -0
  4. package/build/address-book.d.ts +3 -0
  5. package/build/address-book.js +54 -0
  6. package/build/chunk-2UPJKPQ6.js +272 -0
  7. package/build/chunk-EHBM7OXH.js +596 -0
  8. package/build/chunk-LHHKY77D.js +274 -0
  9. package/build/chunk-TGXD24YD.js +279 -0
  10. package/build/chunk-Z2UGRZJ2.js +1635 -0
  11. package/build/command-exports.cjs +1762 -0
  12. package/build/command-exports.d.cts +105 -0
  13. package/build/command-exports.d.ts +105 -0
  14. package/build/command-exports.js +129 -0
  15. package/build/connector/index.cjs +2601 -0
  16. package/build/connector/index.d.cts +55 -0
  17. package/build/connector/index.d.ts +55 -0
  18. package/build/connector/index.js +90 -0
  19. package/build/index.cjs +1634 -1627
  20. package/build/index.d.cts +143 -671
  21. package/build/index.d.ts +143 -671
  22. package/build/index.js +7 -206
  23. package/build/minikit-provider.cjs +1650 -948
  24. package/build/minikit-provider.d.cts +2 -1
  25. package/build/minikit-provider.d.ts +2 -1
  26. package/build/minikit-provider.js +13 -2
  27. package/build/provider-DeDUsLbs.d.cts +43 -0
  28. package/build/provider-DeDUsLbs.d.ts +43 -0
  29. package/build/siwe-exports.cjs +249 -0
  30. package/build/siwe-exports.d.cts +10 -0
  31. package/build/siwe-exports.d.ts +10 -0
  32. package/build/siwe-exports.js +8 -0
  33. package/build/types-CC2x79HX.d.ts +525 -0
  34. package/build/types-CSyzFDPt.d.cts +223 -0
  35. package/build/types-CSyzFDPt.d.ts +223 -0
  36. package/build/types-_jfLbcJW.d.cts +525 -0
  37. package/package.json +73 -11
  38. package/build/chunk-62NZ34E4.js +0 -2092
  39. package/index.ts +0 -29
@@ -0,0 +1,274 @@
1
+ // src/commands/wallet-auth/siwe.ts
2
+ import {
3
+ createPublicClient,
4
+ getContract,
5
+ hashMessage,
6
+ http,
7
+ recoverAddress
8
+ } from "viem";
9
+ import { worldchain } from "viem/chains";
10
+ var PREAMBLE = " wants you to sign in with your Ethereum account:";
11
+ var URI_TAG = "URI: ";
12
+ var VERSION_TAG = "Version: ";
13
+ var CHAIN_TAG = "Chain ID: ";
14
+ var NONCE_TAG = "Nonce: ";
15
+ var IAT_TAG = "Issued At: ";
16
+ var EXP_TAG = "Expiration Time: ";
17
+ var NBF_TAG = "Not Before: ";
18
+ var RID_TAG = "Request ID: ";
19
+ var ERC_191_PREFIX = "Ethereum Signed Message:\n";
20
+ var EIP1271_MAGICVALUE = "0x1626ba7e";
21
+ var SAFE_CONTRACT_ABI = [
22
+ {
23
+ inputs: [
24
+ {
25
+ internalType: "address",
26
+ name: "owner",
27
+ type: "address"
28
+ }
29
+ ],
30
+ name: "isOwner",
31
+ outputs: [
32
+ {
33
+ internalType: "bool",
34
+ name: "",
35
+ type: "bool"
36
+ }
37
+ ],
38
+ stateMutability: "view",
39
+ type: "function"
40
+ },
41
+ {
42
+ inputs: [
43
+ {
44
+ internalType: "bytes32",
45
+ name: "_message",
46
+ type: "bytes32"
47
+ },
48
+ {
49
+ internalType: "bytes",
50
+ name: "_signature",
51
+ type: "bytes"
52
+ }
53
+ ],
54
+ name: "isValidSignature",
55
+ outputs: [
56
+ {
57
+ internalType: "bytes4",
58
+ name: "",
59
+ type: "bytes4"
60
+ }
61
+ ],
62
+ stateMutability: "view",
63
+ type: "function"
64
+ }
65
+ ];
66
+ var tagged = (line, tag) => {
67
+ if (line && line.includes(tag)) {
68
+ return line.replace(tag, "");
69
+ } else {
70
+ throw new Error(`Missing '${tag}'`);
71
+ }
72
+ };
73
+ var parseSiweMessage = (inputString) => {
74
+ const lines = inputString.split("\n")[Symbol.iterator]();
75
+ const domain = tagged(lines.next()?.value, PREAMBLE);
76
+ const address = lines.next()?.value;
77
+ lines.next();
78
+ const nextValue = lines.next()?.value;
79
+ let statement;
80
+ if (nextValue) {
81
+ statement = nextValue;
82
+ lines.next();
83
+ }
84
+ const uri = tagged(lines.next()?.value, URI_TAG);
85
+ const version = tagged(lines.next()?.value, VERSION_TAG);
86
+ const chain_id = tagged(lines.next()?.value, CHAIN_TAG);
87
+ const nonce = tagged(lines.next()?.value, NONCE_TAG);
88
+ const issued_at = tagged(lines.next()?.value, IAT_TAG);
89
+ let expiration_time, not_before, request_id;
90
+ for (let line of lines) {
91
+ if (line.startsWith(EXP_TAG)) {
92
+ expiration_time = tagged(line, EXP_TAG);
93
+ } else if (line.startsWith(NBF_TAG)) {
94
+ not_before = tagged(line, NBF_TAG);
95
+ } else if (line.startsWith(RID_TAG)) {
96
+ request_id = tagged(line, RID_TAG);
97
+ }
98
+ }
99
+ if (lines.next().done === false) {
100
+ throw new Error("Extra lines in the input");
101
+ }
102
+ const siweMessageData = {
103
+ domain,
104
+ address,
105
+ statement,
106
+ uri,
107
+ version,
108
+ chain_id,
109
+ nonce,
110
+ issued_at,
111
+ expiration_time,
112
+ not_before,
113
+ request_id
114
+ };
115
+ return siweMessageData;
116
+ };
117
+ var generateSiweMessage = (siweMessageData) => {
118
+ let siweMessage = "";
119
+ if (siweMessageData.scheme) {
120
+ siweMessage += `${siweMessageData.scheme}://${siweMessageData.domain} wants you to sign in with your Ethereum account:
121
+ `;
122
+ } else {
123
+ siweMessage += `${siweMessageData.domain} wants you to sign in with your Ethereum account:
124
+ `;
125
+ }
126
+ if (siweMessageData.address) {
127
+ siweMessage += `${siweMessageData.address}
128
+ `;
129
+ } else {
130
+ siweMessage += "{address}\n";
131
+ }
132
+ siweMessage += "\n";
133
+ if (siweMessageData.statement) {
134
+ siweMessage += `${siweMessageData.statement}
135
+ `;
136
+ }
137
+ siweMessage += "\n";
138
+ siweMessage += `URI: ${siweMessageData.uri}
139
+ `;
140
+ siweMessage += `Version: ${siweMessageData.version}
141
+ `;
142
+ siweMessage += `Chain ID: ${siweMessageData.chain_id}
143
+ `;
144
+ siweMessage += `Nonce: ${siweMessageData.nonce}
145
+ `;
146
+ siweMessage += `Issued At: ${siweMessageData.issued_at}
147
+ `;
148
+ if (siweMessageData.expiration_time) {
149
+ siweMessage += `Expiration Time: ${siweMessageData.expiration_time}
150
+ `;
151
+ }
152
+ if (siweMessageData.not_before) {
153
+ siweMessage += `Not Before: ${siweMessageData.not_before}
154
+ `;
155
+ }
156
+ if (siweMessageData.request_id) {
157
+ siweMessage += `Request ID: ${siweMessageData.request_id}
158
+ `;
159
+ }
160
+ return siweMessage;
161
+ };
162
+ var verifySiweMessage = (payload, nonce, statement, requestId, userProvider) => {
163
+ if (payload.version === 1) {
164
+ return verifySiweMessageV1(
165
+ payload,
166
+ nonce,
167
+ statement,
168
+ requestId,
169
+ userProvider
170
+ );
171
+ } else {
172
+ return verifySiweMessageV2(
173
+ payload,
174
+ nonce,
175
+ statement,
176
+ requestId,
177
+ userProvider
178
+ );
179
+ }
180
+ };
181
+ var validateMessage = (siweMessageData, nonce, statement, requestId) => {
182
+ if (siweMessageData.expiration_time) {
183
+ const expirationTime = new Date(siweMessageData.expiration_time);
184
+ if (expirationTime < /* @__PURE__ */ new Date()) {
185
+ throw new Error("Expired message");
186
+ }
187
+ }
188
+ if (siweMessageData.not_before) {
189
+ const notBefore = new Date(siweMessageData.not_before);
190
+ if (notBefore > /* @__PURE__ */ new Date()) {
191
+ throw new Error("Not Before time has not passed");
192
+ }
193
+ }
194
+ if (nonce && siweMessageData.nonce !== nonce) {
195
+ throw new Error(
196
+ `Nonce mismatch. Got: ${siweMessageData.nonce}, Expected: ${nonce}`
197
+ );
198
+ }
199
+ if (statement && siweMessageData.statement !== statement) {
200
+ throw new Error(
201
+ `Statement mismatch. Got: ${siweMessageData.statement}, Expected: ${statement}`
202
+ );
203
+ }
204
+ if (requestId && siweMessageData.request_id !== requestId) {
205
+ throw new Error(
206
+ `Request ID mismatch. Got: ${siweMessageData.request_id}, Expected: ${requestId}`
207
+ );
208
+ }
209
+ return true;
210
+ };
211
+ var verifySiweMessageV1 = async (payload, nonce, statement, requestId, userProvider) => {
212
+ if (typeof window !== "undefined") {
213
+ throw new Error("Wallet auth payload can only be verified in the backend");
214
+ }
215
+ const { message, signature, address } = payload;
216
+ const siweMessageData = parseSiweMessage(message);
217
+ validateMessage(siweMessageData, nonce, statement, requestId);
218
+ let provider = userProvider || createPublicClient({ chain: worldchain, transport: http() });
219
+ const signedMessage = `${ERC_191_PREFIX}${message.length}${message}`;
220
+ const hashedMessage = hashMessage(signedMessage);
221
+ const contract = getContract({
222
+ address,
223
+ abi: SAFE_CONTRACT_ABI,
224
+ client: provider
225
+ });
226
+ try {
227
+ const recoveredAddress = await recoverAddress({
228
+ hash: hashedMessage,
229
+ signature: `0x${signature}`
230
+ });
231
+ const isOwner = await contract.read.isOwner([recoveredAddress]);
232
+ if (!isOwner) {
233
+ throw new Error("Signature verification failed, invalid owner");
234
+ }
235
+ } catch (error) {
236
+ throw new Error("Signature verification failed");
237
+ }
238
+ return { isValid: true, siweMessageData };
239
+ };
240
+ var verifySiweMessageV2 = async (payload, nonce, statement, requestId, userProvider) => {
241
+ if (typeof window !== "undefined") {
242
+ throw new Error("Wallet auth payload can only be verified in the backend");
243
+ }
244
+ const { message, signature, address } = payload;
245
+ const siweMessageData = parseSiweMessage(message);
246
+ if (!validateMessage(siweMessageData, nonce, statement, requestId)) {
247
+ throw new Error("Validation failed");
248
+ }
249
+ try {
250
+ const walletContract = getContract({
251
+ address,
252
+ abi: SAFE_CONTRACT_ABI,
253
+ client: userProvider || createPublicClient({ chain: worldchain, transport: http() })
254
+ });
255
+ const hashedMessage = hashMessage(message);
256
+ const res = await walletContract.read.isValidSignature([
257
+ hashedMessage,
258
+ signature
259
+ ]);
260
+ return {
261
+ isValid: res === EIP1271_MAGICVALUE,
262
+ siweMessageData
263
+ };
264
+ } catch (error) {
265
+ console.log(error);
266
+ throw new Error("Signature verification failed");
267
+ }
268
+ };
269
+
270
+ export {
271
+ parseSiweMessage,
272
+ generateSiweMessage,
273
+ verifySiweMessage
274
+ };
@@ -0,0 +1,279 @@
1
+ import {
2
+ MiniKit
3
+ } from "./chunk-EHBM7OXH.js";
4
+
5
+ // src/provider.ts
6
+ import { getAddress } from "viem";
7
+ function _getAddress() {
8
+ if (typeof window === "undefined") return void 0;
9
+ return window.__worldapp_eip1193_address__;
10
+ }
11
+ function _setAddress(addr) {
12
+ if (typeof window === "undefined") return;
13
+ try {
14
+ window.__worldapp_eip1193_address__ = getAddress(addr);
15
+ } catch {
16
+ window.__worldapp_eip1193_address__ = addr;
17
+ }
18
+ }
19
+ function _clearAddress() {
20
+ if (typeof window === "undefined") return;
21
+ window.__worldapp_eip1193_address__ = void 0;
22
+ }
23
+ function rpcError(code, message) {
24
+ return Object.assign(new Error(message), { code });
25
+ }
26
+ function isHexString(value) {
27
+ return /^0x[0-9a-fA-F]*$/.test(value);
28
+ }
29
+ function isAddressString(value) {
30
+ return /^0x[0-9a-fA-F]{40}$/.test(value);
31
+ }
32
+ function decodeHexToUtf8(hex) {
33
+ const raw = hex.slice(2);
34
+ if (raw.length % 2 !== 0) {
35
+ throw new Error("Invalid hex string length");
36
+ }
37
+ const bytes = new Uint8Array(raw.length / 2);
38
+ for (let i = 0; i < raw.length; i += 2) {
39
+ bytes[i / 2] = parseInt(raw.slice(i, i + 2), 16);
40
+ }
41
+ return new TextDecoder().decode(bytes);
42
+ }
43
+ function asArrayParams(params) {
44
+ if (params === void 0) return [];
45
+ return Array.isArray(params) ? params : [params];
46
+ }
47
+ function decodeMaybeHexMessage(value) {
48
+ if (!isHexString(value)) {
49
+ return value;
50
+ }
51
+ try {
52
+ return decodeHexToUtf8(value);
53
+ } catch {
54
+ return value;
55
+ }
56
+ }
57
+ function extractPersonalSignMessage(params) {
58
+ const items = asArrayParams(params);
59
+ if (items.length === 0) {
60
+ throw new Error("Missing personal_sign params");
61
+ }
62
+ const [first, second] = items;
63
+ const maybeMessage = typeof first === "string" && isAddressString(first) && typeof second === "string" ? second : first;
64
+ if (typeof maybeMessage !== "string") {
65
+ throw new Error("Invalid personal_sign message payload");
66
+ }
67
+ return decodeMaybeHexMessage(maybeMessage);
68
+ }
69
+ function extractEthSignMessage(params) {
70
+ const items = asArrayParams(params);
71
+ if (items.length === 0) {
72
+ throw new Error("Missing eth_sign params");
73
+ }
74
+ const [first, second] = items;
75
+ const maybeMessage = typeof second === "string" ? second : typeof first === "string" && !isAddressString(first) ? first : void 0;
76
+ if (typeof maybeMessage !== "string") {
77
+ throw new Error("Invalid eth_sign message payload");
78
+ }
79
+ return decodeMaybeHexMessage(maybeMessage);
80
+ }
81
+ function parseTypedDataInput(params) {
82
+ const items = asArrayParams(params);
83
+ const candidate = items.length > 1 ? items[1] : items[0];
84
+ if (!candidate) {
85
+ throw new Error("Missing typed data payload");
86
+ }
87
+ const parsed = typeof candidate === "string" ? JSON.parse(candidate) : candidate;
88
+ if (!parsed || typeof parsed !== "object" || typeof parsed.primaryType !== "string" || typeof parsed.message !== "object" || !parsed.message || typeof parsed.types !== "object" || !parsed.types) {
89
+ throw new Error("Invalid typed data payload");
90
+ }
91
+ const domainValue = parsed.domain;
92
+ const chainIdValue = domainValue?.chainId ?? parsed.chainId;
93
+ const parsedChainId = typeof chainIdValue === "string" ? Number(chainIdValue) : typeof chainIdValue === "number" ? chainIdValue : void 0;
94
+ return {
95
+ types: parsed.types,
96
+ primaryType: parsed.primaryType,
97
+ domain: domainValue,
98
+ message: parsed.message,
99
+ ...Number.isFinite(parsedChainId) ? { chainId: parsedChainId } : {}
100
+ };
101
+ }
102
+ function normalizeRpcValue(value) {
103
+ if (value === void 0 || value === null) return void 0;
104
+ if (typeof value === "string") return value;
105
+ if (typeof value === "bigint") return `0x${value.toString(16)}`;
106
+ if (typeof value === "number") return `0x${value.toString(16)}`;
107
+ return String(value);
108
+ }
109
+ function extractTransactionParams(params) {
110
+ const items = asArrayParams(params);
111
+ const tx = items[0] ?? {};
112
+ if (typeof tx.to !== "string" || !isAddressString(tx.to)) {
113
+ throw new Error('Invalid transaction "to" address');
114
+ }
115
+ const chainId = typeof tx.chainId === "string" ? Number(tx.chainId) : typeof tx.chainId === "number" ? tx.chainId : void 0;
116
+ const normalizedValue = normalizeRpcValue(tx.value);
117
+ return {
118
+ to: tx.to,
119
+ ...typeof tx.data === "string" ? { data: tx.data } : {},
120
+ ...normalizedValue !== void 0 ? { value: normalizedValue } : {},
121
+ ...Number.isFinite(chainId) ? { chainId } : {}
122
+ };
123
+ }
124
+ function extractSwitchChainId(params) {
125
+ const items = asArrayParams(params);
126
+ const payload = items[0] ?? {};
127
+ const rawChainId = payload.chainId;
128
+ const chainId = typeof rawChainId === "string" ? Number(rawChainId) : typeof rawChainId === "number" ? rawChainId : NaN;
129
+ if (!Number.isFinite(chainId)) {
130
+ throw new Error("Invalid chainId for wallet_switchEthereumChain");
131
+ }
132
+ return chainId;
133
+ }
134
+ function createProvider() {
135
+ const listeners = {};
136
+ function emit(event, ...args) {
137
+ listeners[event]?.forEach((fn) => fn(...args));
138
+ }
139
+ let authInFlight;
140
+ async function doAuth() {
141
+ if (!MiniKit.isInWorldApp() || !MiniKit.isInstalled()) {
142
+ throw rpcError(
143
+ 4900,
144
+ "World App provider only works inside World App and must be installed"
145
+ );
146
+ }
147
+ try {
148
+ const result = await MiniKit.walletAuth({
149
+ nonce: crypto.randomUUID().replace(/-/g, ""),
150
+ statement: "Sign in with World App"
151
+ });
152
+ _setAddress(result.data.address);
153
+ const addr = _getAddress();
154
+ emit("accountsChanged", [addr]);
155
+ return [addr];
156
+ } catch (e) {
157
+ throw rpcError(4001, `World App wallet auth failed: ${e.message}`);
158
+ }
159
+ }
160
+ return {
161
+ async request({ method, params }) {
162
+ switch (method) {
163
+ case "eth_requestAccounts": {
164
+ const existing = _getAddress();
165
+ if (existing) return [existing];
166
+ if (!authInFlight) {
167
+ authInFlight = doAuth().finally(() => {
168
+ authInFlight = void 0;
169
+ });
170
+ }
171
+ return authInFlight;
172
+ }
173
+ case "eth_accounts": {
174
+ const addr = _getAddress();
175
+ return addr ? [addr] : [];
176
+ }
177
+ case "eth_chainId":
178
+ return "0x1e0";
179
+ // 480 = World Chain
180
+ case "personal_sign": {
181
+ const message = extractPersonalSignMessage(params);
182
+ try {
183
+ const result = await MiniKit.signMessage({ message });
184
+ return result.data.signature;
185
+ } catch (e) {
186
+ throw rpcError(4001, `Sign message failed: ${e.message}`);
187
+ }
188
+ }
189
+ case "eth_sign": {
190
+ const message = extractEthSignMessage(params);
191
+ try {
192
+ const result = await MiniKit.signMessage({ message });
193
+ return result.data.signature;
194
+ } catch (e) {
195
+ throw rpcError(4001, `Sign message failed: ${e.message}`);
196
+ }
197
+ }
198
+ case "eth_signTypedData":
199
+ case "eth_signTypedData_v3":
200
+ case "eth_signTypedData_v4": {
201
+ try {
202
+ const typedData = parseTypedDataInput(params);
203
+ const result = await MiniKit.signTypedData({
204
+ types: typedData.types,
205
+ primaryType: typedData.primaryType,
206
+ domain: typedData.domain,
207
+ message: typedData.message,
208
+ chainId: typedData.chainId
209
+ });
210
+ if (result.data.status === "error") {
211
+ throw rpcError(
212
+ 4001,
213
+ `Sign typed data failed: ${result.data.error_code}`
214
+ );
215
+ }
216
+ return result.data.signature;
217
+ } catch (e) {
218
+ throw rpcError(4001, `Sign typed data failed: ${e.message}`);
219
+ }
220
+ }
221
+ case "eth_sendTransaction": {
222
+ const tx = extractTransactionParams(params);
223
+ if (tx.chainId !== void 0 && tx.chainId !== 480) {
224
+ throw rpcError(4902, "World App only supports World Chain (480)");
225
+ }
226
+ try {
227
+ const result = await MiniKit.sendTransaction({
228
+ chainId: tx.chainId ?? 480,
229
+ transactions: [
230
+ {
231
+ to: tx.to,
232
+ ...tx.data && tx.data !== "0x" ? { data: tx.data } : {},
233
+ value: tx.value
234
+ }
235
+ ]
236
+ });
237
+ return result.data.userOpHash;
238
+ } catch (e) {
239
+ throw rpcError(4001, `Send transaction failed: ${e.message}`);
240
+ }
241
+ }
242
+ case "wallet_switchEthereumChain": {
243
+ const chainId = extractSwitchChainId(params);
244
+ if (chainId !== 480) {
245
+ throw rpcError(4902, "World App only supports World Chain (480)");
246
+ }
247
+ return null;
248
+ }
249
+ case "wallet_addEthereumChain": {
250
+ throw rpcError(4200, "World App only supports World Chain (480)");
251
+ }
252
+ default:
253
+ throw rpcError(4200, `Unsupported method: ${method}`);
254
+ }
255
+ },
256
+ on(event, fn) {
257
+ (listeners[event] ?? (listeners[event] = /* @__PURE__ */ new Set())).add(fn);
258
+ },
259
+ removeListener(event, fn) {
260
+ listeners[event]?.delete(fn);
261
+ }
262
+ };
263
+ }
264
+ function getWorldAppProvider() {
265
+ if (typeof window === "undefined") {
266
+ return createProvider();
267
+ }
268
+ if (!window.__worldapp_eip1193_provider__) {
269
+ window.__worldapp_eip1193_provider__ = createProvider();
270
+ }
271
+ return window.__worldapp_eip1193_provider__;
272
+ }
273
+
274
+ export {
275
+ _getAddress,
276
+ _setAddress,
277
+ _clearAddress,
278
+ getWorldAppProvider
279
+ };