@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.
- package/README.md +107 -0
- package/build/address-book.cjs +81 -0
- package/build/address-book.d.cts +3 -0
- package/build/address-book.d.ts +3 -0
- package/build/address-book.js +54 -0
- package/build/chunk-2UPJKPQ6.js +272 -0
- package/build/chunk-EHBM7OXH.js +596 -0
- package/build/chunk-LHHKY77D.js +274 -0
- package/build/chunk-TGXD24YD.js +279 -0
- package/build/chunk-Z2UGRZJ2.js +1635 -0
- package/build/command-exports.cjs +1762 -0
- package/build/command-exports.d.cts +105 -0
- package/build/command-exports.d.ts +105 -0
- package/build/command-exports.js +129 -0
- package/build/connector/index.cjs +2601 -0
- package/build/connector/index.d.cts +55 -0
- package/build/connector/index.d.ts +55 -0
- package/build/connector/index.js +90 -0
- package/build/index.cjs +1634 -1627
- package/build/index.d.cts +143 -671
- package/build/index.d.ts +143 -671
- package/build/index.js +7 -206
- package/build/minikit-provider.cjs +1650 -948
- package/build/minikit-provider.d.cts +2 -1
- package/build/minikit-provider.d.ts +2 -1
- package/build/minikit-provider.js +13 -2
- package/build/provider-DeDUsLbs.d.cts +43 -0
- package/build/provider-DeDUsLbs.d.ts +43 -0
- package/build/siwe-exports.cjs +249 -0
- package/build/siwe-exports.d.cts +10 -0
- package/build/siwe-exports.d.ts +10 -0
- package/build/siwe-exports.js +8 -0
- package/build/types-CC2x79HX.d.ts +525 -0
- package/build/types-CSyzFDPt.d.cts +223 -0
- package/build/types-CSyzFDPt.d.ts +223 -0
- package/build/types-_jfLbcJW.d.cts +525 -0
- package/package.json +73 -11
- package/build/chunk-62NZ34E4.js +0 -2092
- package/index.ts +0 -29
|
@@ -0,0 +1,2601 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/connector/index.ts
|
|
31
|
+
var connector_exports = {};
|
|
32
|
+
__export(connector_exports, {
|
|
33
|
+
worldApp: () => worldApp
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(connector_exports);
|
|
36
|
+
|
|
37
|
+
// src/commands/fallback-adapter-registry.ts
|
|
38
|
+
var FALLBACK_ADAPTER_KEY = "__minikit_fallback_adapter__";
|
|
39
|
+
function setFallbackAdapter(adapter) {
|
|
40
|
+
globalThis[FALLBACK_ADAPTER_KEY] = adapter;
|
|
41
|
+
}
|
|
42
|
+
function getFallbackAdapter() {
|
|
43
|
+
return globalThis[FALLBACK_ADAPTER_KEY];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/commands/wagmi-fallback.ts
|
|
47
|
+
var SIWE_NONCE_REGEX = /^[a-zA-Z0-9]{8,}$/;
|
|
48
|
+
var WAGMI_KEY = "__minikit_wagmi_config__";
|
|
49
|
+
function setWagmiConfig(config) {
|
|
50
|
+
globalThis[WAGMI_KEY] = config;
|
|
51
|
+
registerWagmiFallbacks();
|
|
52
|
+
}
|
|
53
|
+
function getWagmiConfig() {
|
|
54
|
+
return globalThis[WAGMI_KEY];
|
|
55
|
+
}
|
|
56
|
+
function hasWagmiConfig() {
|
|
57
|
+
return globalThis[WAGMI_KEY] !== void 0;
|
|
58
|
+
}
|
|
59
|
+
function registerWagmiFallbacks() {
|
|
60
|
+
setFallbackAdapter({
|
|
61
|
+
walletAuth: wagmiWalletAuth,
|
|
62
|
+
signMessage: wagmiSignMessage,
|
|
63
|
+
signTypedData: wagmiSignTypedData,
|
|
64
|
+
sendTransaction: wagmiSendTransaction
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async function loadWagmiActions() {
|
|
68
|
+
console.log("[MiniKit WagmiFallback] loadWagmiActions:start", {
|
|
69
|
+
hasWindow: typeof window !== "undefined",
|
|
70
|
+
hasWagmiConfig: hasWagmiConfig()
|
|
71
|
+
});
|
|
72
|
+
try {
|
|
73
|
+
const actions = await import(
|
|
74
|
+
/* webpackIgnore: true */
|
|
75
|
+
"wagmi/actions"
|
|
76
|
+
);
|
|
77
|
+
console.log("[MiniKit WagmiFallback] loadWagmiActions:success");
|
|
78
|
+
return actions;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.log("[MiniKit WagmiFallback] loadWagmiActions:error", {
|
|
81
|
+
message: error instanceof Error ? error.message : String(error)
|
|
82
|
+
});
|
|
83
|
+
const wrappedError = new Error(
|
|
84
|
+
'Wagmi fallback requires the "wagmi" package. Install wagmi or provide a custom fallback.'
|
|
85
|
+
);
|
|
86
|
+
wrappedError.cause = error;
|
|
87
|
+
throw wrappedError;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function loadSiwe() {
|
|
91
|
+
try {
|
|
92
|
+
return await import(
|
|
93
|
+
/* webpackIgnore: true */
|
|
94
|
+
"siwe"
|
|
95
|
+
);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
const wrappedError = new Error(
|
|
98
|
+
'Wagmi walletAuth fallback requires the "siwe" package. Install siwe or provide a custom fallback.'
|
|
99
|
+
);
|
|
100
|
+
wrappedError.cause = error;
|
|
101
|
+
throw wrappedError;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function checksumAddress(addr) {
|
|
105
|
+
try {
|
|
106
|
+
const { getAddress: getAddress2 } = await import(
|
|
107
|
+
/* webpackIgnore: true */
|
|
108
|
+
"viem"
|
|
109
|
+
);
|
|
110
|
+
return getAddress2(addr);
|
|
111
|
+
} catch {
|
|
112
|
+
return addr;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function ensureConnected(config) {
|
|
116
|
+
const { connect, getConnections } = await loadWagmiActions();
|
|
117
|
+
const isWorldApp = typeof window !== "undefined" && Boolean(window.WorldApp);
|
|
118
|
+
const existingConnection = getConnections(config).find(
|
|
119
|
+
(connection) => connection.accounts && connection.accounts.length > 0 && (isWorldApp || connection.connector?.id !== "worldApp")
|
|
120
|
+
);
|
|
121
|
+
if (existingConnection && existingConnection.accounts) {
|
|
122
|
+
return checksumAddress(existingConnection.accounts[0]);
|
|
123
|
+
}
|
|
124
|
+
const connectors = config.connectors;
|
|
125
|
+
if (!connectors || connectors.length === 0) {
|
|
126
|
+
throw new Error("No Wagmi connectors configured");
|
|
127
|
+
}
|
|
128
|
+
const candidateConnectors = isWorldApp ? connectors : connectors.filter(
|
|
129
|
+
(connector) => connector.id !== "worldApp"
|
|
130
|
+
);
|
|
131
|
+
if (!isWorldApp && candidateConnectors.length === 0) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
"No web Wagmi connectors configured. Add a web connector (e.g. injected or walletConnect) after worldApp()."
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
const selectedConnector = candidateConnectors[0];
|
|
137
|
+
try {
|
|
138
|
+
const result = await connect(config, { connector: selectedConnector });
|
|
139
|
+
if (result.accounts.length > 0) {
|
|
140
|
+
const account = result.accounts[0];
|
|
141
|
+
const address = typeof account === "string" ? account : account.address;
|
|
142
|
+
if (address) {
|
|
143
|
+
return checksumAddress(address);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
} catch (error) {
|
|
147
|
+
const connectorId = selectedConnector.id ?? "unknown";
|
|
148
|
+
const wrappedError = new Error(
|
|
149
|
+
`Failed to connect with connector "${connectorId}". Reorder connectors to change the default connector.`
|
|
150
|
+
);
|
|
151
|
+
wrappedError.cause = error;
|
|
152
|
+
throw wrappedError;
|
|
153
|
+
}
|
|
154
|
+
throw new Error("Failed to connect wallet");
|
|
155
|
+
}
|
|
156
|
+
async function wagmiWalletAuth(params) {
|
|
157
|
+
console.log("[MiniKit WagmiFallback] walletAuth:start", {
|
|
158
|
+
hasWagmiConfig: hasWagmiConfig(),
|
|
159
|
+
nonceLength: params.nonce?.length ?? 0
|
|
160
|
+
});
|
|
161
|
+
const config = getWagmiConfig();
|
|
162
|
+
if (!config) {
|
|
163
|
+
console.log("[MiniKit WagmiFallback] walletAuth:error:no-config");
|
|
164
|
+
throw new Error(
|
|
165
|
+
"Wagmi config not available. Pass wagmiConfig to MiniKitProvider."
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
const { signMessage: signMessage2 } = await loadWagmiActions();
|
|
169
|
+
const { SiweMessage } = await loadSiwe();
|
|
170
|
+
const address = await ensureConnected(config);
|
|
171
|
+
if (!SIWE_NONCE_REGEX.test(params.nonce)) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
"Invalid nonce: must be alphanumeric and at least 8 characters (EIP-4361)"
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
const siweMessage = new SiweMessage({
|
|
177
|
+
domain: typeof window !== "undefined" ? window.location.host : "localhost",
|
|
178
|
+
address,
|
|
179
|
+
statement: params.statement,
|
|
180
|
+
uri: typeof window !== "undefined" ? window.location.origin : "http://localhost",
|
|
181
|
+
version: "1",
|
|
182
|
+
chainId: 480,
|
|
183
|
+
// World Chain
|
|
184
|
+
nonce: params.nonce,
|
|
185
|
+
expirationTime: params.expirationTime?.toISOString()
|
|
186
|
+
});
|
|
187
|
+
const message = siweMessage.prepareMessage();
|
|
188
|
+
const signature = await signMessage2(config, { message });
|
|
189
|
+
return {
|
|
190
|
+
address,
|
|
191
|
+
message,
|
|
192
|
+
signature
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
async function wagmiSignMessage(params) {
|
|
196
|
+
console.log("[MiniKit WagmiFallback] signMessage:start", {
|
|
197
|
+
hasWagmiConfig: hasWagmiConfig()
|
|
198
|
+
});
|
|
199
|
+
const config = getWagmiConfig();
|
|
200
|
+
if (!config) {
|
|
201
|
+
console.log("[MiniKit WagmiFallback] signMessage:error:no-config");
|
|
202
|
+
throw new Error(
|
|
203
|
+
"Wagmi config not available. Pass wagmiConfig to MiniKitProvider."
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
const { signMessage: signMessage2 } = await loadWagmiActions();
|
|
207
|
+
const address = await ensureConnected(config);
|
|
208
|
+
const signature = await signMessage2(config, {
|
|
209
|
+
account: address,
|
|
210
|
+
message: params.message
|
|
211
|
+
});
|
|
212
|
+
return {
|
|
213
|
+
status: "success",
|
|
214
|
+
version: 1,
|
|
215
|
+
signature,
|
|
216
|
+
address
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
async function wagmiSignTypedData(params) {
|
|
220
|
+
console.log("[MiniKit WagmiFallback] signTypedData:start", {
|
|
221
|
+
hasWagmiConfig: hasWagmiConfig(),
|
|
222
|
+
hasChainId: params.chainId !== void 0
|
|
223
|
+
});
|
|
224
|
+
const config = getWagmiConfig();
|
|
225
|
+
if (!config) {
|
|
226
|
+
console.log("[MiniKit WagmiFallback] signTypedData:error:no-config");
|
|
227
|
+
throw new Error(
|
|
228
|
+
"Wagmi config not available. Pass wagmiConfig to MiniKitProvider."
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
const { getChainId, signTypedData: signTypedData2, switchChain } = await loadWagmiActions();
|
|
232
|
+
const address = await ensureConnected(config);
|
|
233
|
+
if (params.chainId !== void 0) {
|
|
234
|
+
const currentChainId = await getChainId(config);
|
|
235
|
+
if (currentChainId !== params.chainId) {
|
|
236
|
+
await switchChain(config, { chainId: params.chainId });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const signature = await signTypedData2(config, {
|
|
240
|
+
account: address,
|
|
241
|
+
types: params.types,
|
|
242
|
+
primaryType: params.primaryType,
|
|
243
|
+
domain: params.domain,
|
|
244
|
+
message: params.message
|
|
245
|
+
});
|
|
246
|
+
return {
|
|
247
|
+
status: "success",
|
|
248
|
+
version: 1,
|
|
249
|
+
signature,
|
|
250
|
+
address
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function isChainMismatchError(error) {
|
|
254
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
255
|
+
return message.includes("does not match the target chain");
|
|
256
|
+
}
|
|
257
|
+
async function wagmiSendTransaction(params) {
|
|
258
|
+
console.log("[MiniKit WagmiFallback] sendTransaction:start", {
|
|
259
|
+
hasWagmiConfig: hasWagmiConfig(),
|
|
260
|
+
chainId: params.chainId,
|
|
261
|
+
hasData: Boolean(params.transaction.data)
|
|
262
|
+
});
|
|
263
|
+
const config = getWagmiConfig();
|
|
264
|
+
if (!config) {
|
|
265
|
+
console.log("[MiniKit WagmiFallback] sendTransaction:error:no-config");
|
|
266
|
+
throw new Error(
|
|
267
|
+
"Wagmi config not available. Pass wagmiConfig to MiniKitProvider."
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
const { getChainId, getWalletClient, sendTransaction: sendTransaction2, switchChain } = await loadWagmiActions();
|
|
271
|
+
await ensureConnected(config);
|
|
272
|
+
const targetChainId = params.chainId ?? config.chains?.[0]?.id;
|
|
273
|
+
const ensureTargetChain = async () => {
|
|
274
|
+
if (targetChainId === void 0) return;
|
|
275
|
+
const currentChainId = await getChainId(config);
|
|
276
|
+
if (currentChainId !== targetChainId) {
|
|
277
|
+
await switchChain(config, { chainId: targetChainId });
|
|
278
|
+
}
|
|
279
|
+
const walletClient = await getWalletClient(config);
|
|
280
|
+
const providerChainId = walletClient ? await walletClient.getChainId() : await getChainId(config);
|
|
281
|
+
if (providerChainId !== targetChainId) {
|
|
282
|
+
throw new Error(
|
|
283
|
+
`Wallet network mismatch: expected chain ${targetChainId}, got ${providerChainId}. Please switch networks in your wallet and retry.`
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
await ensureTargetChain();
|
|
288
|
+
let transactionHash;
|
|
289
|
+
try {
|
|
290
|
+
transactionHash = await sendTransaction2(config, {
|
|
291
|
+
chainId: targetChainId,
|
|
292
|
+
to: params.transaction.address,
|
|
293
|
+
data: params.transaction.data,
|
|
294
|
+
value: params.transaction.value ? BigInt(params.transaction.value) : void 0
|
|
295
|
+
});
|
|
296
|
+
} catch (error) {
|
|
297
|
+
if (targetChainId === void 0 || !isChainMismatchError(error)) {
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
await ensureTargetChain();
|
|
301
|
+
transactionHash = await sendTransaction2(config, {
|
|
302
|
+
chainId: targetChainId,
|
|
303
|
+
to: params.transaction.address,
|
|
304
|
+
data: params.transaction.data,
|
|
305
|
+
value: params.transaction.value ? BigInt(params.transaction.value) : void 0
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
return { transactionHash };
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/commands/types.ts
|
|
312
|
+
var COMMAND_VERSIONS = {
|
|
313
|
+
["attestation" /* Attestation */]: 1,
|
|
314
|
+
["pay" /* Pay */]: 1,
|
|
315
|
+
["wallet-auth" /* WalletAuth */]: 2,
|
|
316
|
+
["send-transaction" /* SendTransaction */]: 2,
|
|
317
|
+
["sign-message" /* SignMessage */]: 1,
|
|
318
|
+
["sign-typed-data" /* SignTypedData */]: 1,
|
|
319
|
+
["share-contacts" /* ShareContacts */]: 1,
|
|
320
|
+
["request-permission" /* RequestPermission */]: 1,
|
|
321
|
+
["get-permissions" /* GetPermissions */]: 1,
|
|
322
|
+
["send-haptic-feedback" /* SendHapticFeedback */]: 1,
|
|
323
|
+
["share" /* Share */]: 1,
|
|
324
|
+
["chat" /* Chat */]: 1,
|
|
325
|
+
["close-miniapp" /* CloseMiniApp */]: 1
|
|
326
|
+
};
|
|
327
|
+
var commandAvailability = {
|
|
328
|
+
["attestation" /* Attestation */]: false,
|
|
329
|
+
["pay" /* Pay */]: false,
|
|
330
|
+
["wallet-auth" /* WalletAuth */]: false,
|
|
331
|
+
["send-transaction" /* SendTransaction */]: false,
|
|
332
|
+
["sign-message" /* SignMessage */]: false,
|
|
333
|
+
["sign-typed-data" /* SignTypedData */]: false,
|
|
334
|
+
["share-contacts" /* ShareContacts */]: false,
|
|
335
|
+
["request-permission" /* RequestPermission */]: false,
|
|
336
|
+
["get-permissions" /* GetPermissions */]: false,
|
|
337
|
+
["send-haptic-feedback" /* SendHapticFeedback */]: false,
|
|
338
|
+
["share" /* Share */]: false,
|
|
339
|
+
["chat" /* Chat */]: false,
|
|
340
|
+
["close-miniapp" /* CloseMiniApp */]: false
|
|
341
|
+
};
|
|
342
|
+
function isCommandAvailable(command) {
|
|
343
|
+
return commandAvailability[command] ?? false;
|
|
344
|
+
}
|
|
345
|
+
function setCommandAvailable(command, available) {
|
|
346
|
+
commandAvailability[command] = available;
|
|
347
|
+
}
|
|
348
|
+
function validateCommands(worldAppSupportedCommands) {
|
|
349
|
+
let allCommandsValid = true;
|
|
350
|
+
Object.entries(COMMAND_VERSIONS).forEach(([commandName, version]) => {
|
|
351
|
+
const commandInput = worldAppSupportedCommands.find(
|
|
352
|
+
(cmd) => cmd.name === commandName
|
|
353
|
+
);
|
|
354
|
+
let isCommandValid = false;
|
|
355
|
+
if (!commandInput) {
|
|
356
|
+
console.warn(
|
|
357
|
+
`Command ${commandName} is not supported by the app. Try updating the app version`
|
|
358
|
+
);
|
|
359
|
+
} else {
|
|
360
|
+
if (commandInput.supported_versions.includes(version)) {
|
|
361
|
+
setCommandAvailable(commandName, true);
|
|
362
|
+
isCommandValid = true;
|
|
363
|
+
} else {
|
|
364
|
+
isCommandValid = true;
|
|
365
|
+
console.warn(
|
|
366
|
+
`Command ${commandName} version ${version} is not supported by the app. Supported versions: ${commandInput.supported_versions.join(", ")}. This is not an error, but it is recommended to update the World App version.`
|
|
367
|
+
);
|
|
368
|
+
setCommandAvailable(commandName, true);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if (!isCommandValid) {
|
|
372
|
+
allCommandsValid = false;
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
return allCommandsValid;
|
|
376
|
+
}
|
|
377
|
+
function sendMiniKitEvent(payload) {
|
|
378
|
+
if (window.webkit) {
|
|
379
|
+
window.webkit?.messageHandlers?.minikit?.postMessage?.(payload);
|
|
380
|
+
} else if (window.Android) {
|
|
381
|
+
window.Android?.postMessage?.(JSON.stringify(payload));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
function isInWorldApp() {
|
|
385
|
+
return typeof window !== "undefined" && Boolean(window.WorldApp);
|
|
386
|
+
}
|
|
387
|
+
var FallbackRequiredError = class extends Error {
|
|
388
|
+
constructor(command) {
|
|
389
|
+
super(
|
|
390
|
+
`${command} requires a fallback function when running outside World App. Provide a fallback option: MiniKit.${command}({ ..., fallback: () => yourFallback() })`
|
|
391
|
+
);
|
|
392
|
+
this.name = "FallbackRequiredError";
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
var CommandUnavailableError = class extends Error {
|
|
396
|
+
constructor(command, reason) {
|
|
397
|
+
const messages = {
|
|
398
|
+
notInWorldApp: "Not running inside World App",
|
|
399
|
+
commandNotSupported: "Command not supported in this environment",
|
|
400
|
+
oldAppVersion: "World App version does not support this command"
|
|
401
|
+
};
|
|
402
|
+
super(`${command} is unavailable: ${messages[reason]}`);
|
|
403
|
+
this.name = "CommandUnavailableError";
|
|
404
|
+
this.reason = reason;
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
// src/events.ts
|
|
409
|
+
var EventManager = class {
|
|
410
|
+
constructor() {
|
|
411
|
+
this.listeners = {
|
|
412
|
+
["miniapp-attestation" /* MiniAppAttestation */]: () => {
|
|
413
|
+
},
|
|
414
|
+
["miniapp-payment" /* MiniAppPayment */]: () => {
|
|
415
|
+
},
|
|
416
|
+
["miniapp-wallet-auth" /* MiniAppWalletAuth */]: () => {
|
|
417
|
+
},
|
|
418
|
+
["miniapp-send-transaction" /* MiniAppSendTransaction */]: () => {
|
|
419
|
+
},
|
|
420
|
+
["miniapp-sign-message" /* MiniAppSignMessage */]: () => {
|
|
421
|
+
},
|
|
422
|
+
["miniapp-sign-typed-data" /* MiniAppSignTypedData */]: () => {
|
|
423
|
+
},
|
|
424
|
+
["miniapp-share-contacts" /* MiniAppShareContacts */]: () => {
|
|
425
|
+
},
|
|
426
|
+
["miniapp-request-permission" /* MiniAppRequestPermission */]: () => {
|
|
427
|
+
},
|
|
428
|
+
["miniapp-get-permissions" /* MiniAppGetPermissions */]: () => {
|
|
429
|
+
},
|
|
430
|
+
["miniapp-send-haptic-feedback" /* MiniAppSendHapticFeedback */]: () => {
|
|
431
|
+
},
|
|
432
|
+
["miniapp-share" /* MiniAppShare */]: () => {
|
|
433
|
+
},
|
|
434
|
+
["miniapp-microphone" /* MiniAppMicrophone */]: () => {
|
|
435
|
+
},
|
|
436
|
+
["miniapp-chat" /* MiniAppChat */]: () => {
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
subscribe(event, handler) {
|
|
441
|
+
this.listeners[event] = handler;
|
|
442
|
+
}
|
|
443
|
+
unsubscribe(event) {
|
|
444
|
+
delete this.listeners[event];
|
|
445
|
+
}
|
|
446
|
+
trigger(event, payload) {
|
|
447
|
+
if (!this.listeners[event]) {
|
|
448
|
+
console.error(
|
|
449
|
+
`No handler for event ${event}, payload: ${JSON.stringify(payload)}`
|
|
450
|
+
);
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
this.listeners[event](payload);
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
// src/commands/fallback.ts
|
|
458
|
+
async function executeWithFallback(options) {
|
|
459
|
+
const {
|
|
460
|
+
command,
|
|
461
|
+
nativeExecutor,
|
|
462
|
+
wagmiFallback,
|
|
463
|
+
customFallback,
|
|
464
|
+
requiresFallback = false
|
|
465
|
+
} = options;
|
|
466
|
+
const inWorldApp = isInWorldApp();
|
|
467
|
+
const commandAvailable = isCommandAvailable(command);
|
|
468
|
+
let nativeError;
|
|
469
|
+
if (inWorldApp && commandAvailable) {
|
|
470
|
+
try {
|
|
471
|
+
const data = await nativeExecutor();
|
|
472
|
+
return { data, executedWith: "minikit" };
|
|
473
|
+
} catch (error) {
|
|
474
|
+
nativeError = error;
|
|
475
|
+
console.warn(`Native ${command} failed, attempting fallback:`, error);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
if (!inWorldApp && wagmiFallback) {
|
|
479
|
+
try {
|
|
480
|
+
const data = await wagmiFallback();
|
|
481
|
+
return { data, executedWith: "wagmi" };
|
|
482
|
+
} catch (error) {
|
|
483
|
+
console.warn(`Wagmi fallback for ${command} failed:`, error);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
if (!inWorldApp && customFallback) {
|
|
487
|
+
const data = await customFallback();
|
|
488
|
+
return { data, executedWith: "fallback" };
|
|
489
|
+
}
|
|
490
|
+
if (nativeError) {
|
|
491
|
+
throw nativeError;
|
|
492
|
+
}
|
|
493
|
+
if (requiresFallback && !inWorldApp) {
|
|
494
|
+
throw new FallbackRequiredError(command);
|
|
495
|
+
}
|
|
496
|
+
throw new CommandUnavailableError(command, determineFallbackReason(command));
|
|
497
|
+
}
|
|
498
|
+
function determineFallbackReason(command) {
|
|
499
|
+
if (!isInWorldApp()) {
|
|
500
|
+
return "notInWorldApp";
|
|
501
|
+
}
|
|
502
|
+
if (!isCommandAvailable(command)) {
|
|
503
|
+
return "oldAppVersion";
|
|
504
|
+
}
|
|
505
|
+
return "commandNotSupported";
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// src/commands/attestation/types.ts
|
|
509
|
+
var AttestationError = class extends Error {
|
|
510
|
+
constructor(error_code) {
|
|
511
|
+
super(`Attestation failed: ${error_code}`);
|
|
512
|
+
this.error_code = error_code;
|
|
513
|
+
this.name = "AttestationError";
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
// src/commands/attestation/index.ts
|
|
518
|
+
async function attestation(options, ctx) {
|
|
519
|
+
const result = await executeWithFallback({
|
|
520
|
+
command: "attestation" /* Attestation */,
|
|
521
|
+
nativeExecutor: () => nativeAttestation(options, ctx),
|
|
522
|
+
customFallback: options.fallback
|
|
523
|
+
});
|
|
524
|
+
if (result.executedWith === "fallback") {
|
|
525
|
+
return { executedWith: "fallback", data: result.data };
|
|
526
|
+
}
|
|
527
|
+
return {
|
|
528
|
+
executedWith: "minikit",
|
|
529
|
+
data: result.data
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
async function nativeAttestation(options, ctx) {
|
|
533
|
+
if (!ctx) {
|
|
534
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
535
|
+
}
|
|
536
|
+
if (typeof window === "undefined" || !isCommandAvailable("attestation" /* Attestation */)) {
|
|
537
|
+
throw new Error(
|
|
538
|
+
"'attestation' command is unavailable. Check MiniKit.install() or update the app version"
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
if (!options.requestHash || options.requestHash.length === 0) {
|
|
542
|
+
throw new Error("'attestation' command requires a non-empty requestHash");
|
|
543
|
+
}
|
|
544
|
+
const payload = await new Promise(
|
|
545
|
+
(resolve, reject) => {
|
|
546
|
+
try {
|
|
547
|
+
ctx.events.subscribe("miniapp-attestation" /* MiniAppAttestation */, (response) => {
|
|
548
|
+
ctx.events.unsubscribe("miniapp-attestation" /* MiniAppAttestation */);
|
|
549
|
+
resolve(response);
|
|
550
|
+
});
|
|
551
|
+
sendMiniKitEvent({
|
|
552
|
+
command: "attestation" /* Attestation */,
|
|
553
|
+
version: COMMAND_VERSIONS["attestation" /* Attestation */],
|
|
554
|
+
payload: {
|
|
555
|
+
request_hash: options.requestHash
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
} catch (error) {
|
|
559
|
+
reject(error);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
);
|
|
563
|
+
if (payload.status === "error") {
|
|
564
|
+
throw new AttestationError(payload.error_code);
|
|
565
|
+
}
|
|
566
|
+
return payload;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// src/commands/chat/types.ts
|
|
570
|
+
var ChatError = class extends Error {
|
|
571
|
+
constructor(error_code) {
|
|
572
|
+
super(`Chat failed: ${error_code}`);
|
|
573
|
+
this.error_code = error_code;
|
|
574
|
+
this.name = "ChatError";
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
// src/commands/chat/index.ts
|
|
579
|
+
async function chat(options, ctx) {
|
|
580
|
+
const result = await executeWithFallback({
|
|
581
|
+
command: "chat" /* Chat */,
|
|
582
|
+
nativeExecutor: () => nativeChat(options, ctx),
|
|
583
|
+
customFallback: options.fallback
|
|
584
|
+
});
|
|
585
|
+
if (result.executedWith === "fallback") {
|
|
586
|
+
return { executedWith: "fallback", data: result.data };
|
|
587
|
+
}
|
|
588
|
+
return {
|
|
589
|
+
executedWith: "minikit",
|
|
590
|
+
data: result.data
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
async function nativeChat(options, ctx) {
|
|
594
|
+
if (!ctx) {
|
|
595
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
596
|
+
}
|
|
597
|
+
if (typeof window === "undefined" || !isCommandAvailable("chat" /* Chat */)) {
|
|
598
|
+
throw new Error(
|
|
599
|
+
"'chat' command is unavailable. Check MiniKit.install() or update the app version"
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
const payloadInput = {
|
|
603
|
+
message: options.message,
|
|
604
|
+
to: options.to
|
|
605
|
+
};
|
|
606
|
+
if (payloadInput.message.length === 0) {
|
|
607
|
+
throw new Error("'chat' command requires a non-empty message");
|
|
608
|
+
}
|
|
609
|
+
const payload = await new Promise((resolve, reject) => {
|
|
610
|
+
try {
|
|
611
|
+
ctx.events.subscribe("miniapp-chat" /* MiniAppChat */, (response) => {
|
|
612
|
+
ctx.events.unsubscribe("miniapp-chat" /* MiniAppChat */);
|
|
613
|
+
resolve(response);
|
|
614
|
+
});
|
|
615
|
+
sendMiniKitEvent({
|
|
616
|
+
command: "chat" /* Chat */,
|
|
617
|
+
version: COMMAND_VERSIONS["chat" /* Chat */],
|
|
618
|
+
payload: payloadInput
|
|
619
|
+
});
|
|
620
|
+
} catch (error) {
|
|
621
|
+
reject(error);
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
if (payload.status === "error") {
|
|
625
|
+
throw new ChatError(payload.error_code);
|
|
626
|
+
}
|
|
627
|
+
return payload;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// src/commands/close-miniapp/index.ts
|
|
631
|
+
async function closeMiniApp(options = {}, _ctx) {
|
|
632
|
+
const result = await executeWithFallback({
|
|
633
|
+
command: "close-miniapp" /* CloseMiniApp */,
|
|
634
|
+
nativeExecutor: () => nativeCloseMiniApp(),
|
|
635
|
+
customFallback: options.fallback
|
|
636
|
+
});
|
|
637
|
+
if (result.executedWith === "fallback") {
|
|
638
|
+
return { executedWith: "fallback", data: result.data };
|
|
639
|
+
}
|
|
640
|
+
return {
|
|
641
|
+
executedWith: "minikit",
|
|
642
|
+
data: result.data
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
async function nativeCloseMiniApp() {
|
|
646
|
+
if (typeof window === "undefined" || !isCommandAvailable("close-miniapp" /* CloseMiniApp */)) {
|
|
647
|
+
throw new Error(
|
|
648
|
+
"'closeMiniApp' command is unavailable. Check MiniKit.install() or update the app version"
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
sendMiniKitEvent({
|
|
652
|
+
command: "close-miniapp" /* CloseMiniApp */,
|
|
653
|
+
version: COMMAND_VERSIONS["close-miniapp" /* CloseMiniApp */],
|
|
654
|
+
payload: {}
|
|
655
|
+
});
|
|
656
|
+
return {
|
|
657
|
+
status: "success",
|
|
658
|
+
version: COMMAND_VERSIONS["close-miniapp" /* CloseMiniApp */]
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// src/commands/get-permissions/types.ts
|
|
663
|
+
var GetPermissionsError = class extends Error {
|
|
664
|
+
constructor(error_code) {
|
|
665
|
+
super(`Get permissions failed: ${error_code}`);
|
|
666
|
+
this.error_code = error_code;
|
|
667
|
+
this.name = "GetPermissionsError";
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
// src/commands/get-permissions/index.ts
|
|
672
|
+
async function getPermissions(options, ctx) {
|
|
673
|
+
const resolvedOptions = options ?? {};
|
|
674
|
+
const result = await executeWithFallback({
|
|
675
|
+
command: "get-permissions" /* GetPermissions */,
|
|
676
|
+
nativeExecutor: () => nativeGetPermissions(ctx),
|
|
677
|
+
customFallback: resolvedOptions.fallback
|
|
678
|
+
});
|
|
679
|
+
if (result.executedWith === "fallback") {
|
|
680
|
+
return { executedWith: "fallback", data: result.data };
|
|
681
|
+
}
|
|
682
|
+
return {
|
|
683
|
+
executedWith: "minikit",
|
|
684
|
+
data: result.data
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
async function nativeGetPermissions(ctx) {
|
|
688
|
+
if (!ctx) {
|
|
689
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
690
|
+
}
|
|
691
|
+
if (typeof window === "undefined" || !isCommandAvailable("get-permissions" /* GetPermissions */)) {
|
|
692
|
+
throw new Error(
|
|
693
|
+
"'getPermissions' command is unavailable. Check MiniKit.install() or update the app version"
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
const payload = await new Promise(
|
|
697
|
+
(resolve, reject) => {
|
|
698
|
+
try {
|
|
699
|
+
ctx.events.subscribe("miniapp-get-permissions" /* MiniAppGetPermissions */, (response) => {
|
|
700
|
+
ctx.events.unsubscribe("miniapp-get-permissions" /* MiniAppGetPermissions */);
|
|
701
|
+
resolve(response);
|
|
702
|
+
});
|
|
703
|
+
sendMiniKitEvent({
|
|
704
|
+
command: "get-permissions" /* GetPermissions */,
|
|
705
|
+
version: COMMAND_VERSIONS["get-permissions" /* GetPermissions */],
|
|
706
|
+
payload: {}
|
|
707
|
+
});
|
|
708
|
+
} catch (error) {
|
|
709
|
+
reject(error);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
);
|
|
713
|
+
if (payload.status === "error") {
|
|
714
|
+
throw new GetPermissionsError(payload.error_code);
|
|
715
|
+
}
|
|
716
|
+
return payload;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// src/commands/pay/types.ts
|
|
720
|
+
var PayError = class extends Error {
|
|
721
|
+
constructor(code) {
|
|
722
|
+
super(`Payment failed: ${code}`);
|
|
723
|
+
this.name = "PayError";
|
|
724
|
+
this.code = code;
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
// src/commands/pay/validate.ts
|
|
729
|
+
var validatePaymentPayload = (payload) => {
|
|
730
|
+
if (payload.tokens.some(
|
|
731
|
+
(token) => token.symbol == "USDCE" /* USDC */ && parseFloat(token.token_amount) < 0.1
|
|
732
|
+
)) {
|
|
733
|
+
console.error("USDC amount should be greater than $0.1");
|
|
734
|
+
return false;
|
|
735
|
+
}
|
|
736
|
+
if (payload.reference.length > 36) {
|
|
737
|
+
console.error("Reference must not exceed 36 characters");
|
|
738
|
+
return false;
|
|
739
|
+
}
|
|
740
|
+
if (typeof payload.reference !== "string") {
|
|
741
|
+
throw new Error("Reference must be a string");
|
|
742
|
+
}
|
|
743
|
+
return true;
|
|
744
|
+
};
|
|
745
|
+
|
|
746
|
+
// src/commands/pay/index.ts
|
|
747
|
+
async function pay(options, ctx) {
|
|
748
|
+
const result = await executeWithFallback({
|
|
749
|
+
command: "pay" /* Pay */,
|
|
750
|
+
nativeExecutor: () => nativePay(options, ctx),
|
|
751
|
+
// No Wagmi fallback - pay is native only
|
|
752
|
+
customFallback: options.fallback
|
|
753
|
+
});
|
|
754
|
+
if (result.executedWith === "fallback") {
|
|
755
|
+
return { executedWith: "fallback", data: result.data };
|
|
756
|
+
}
|
|
757
|
+
return { executedWith: "minikit", data: result.data };
|
|
758
|
+
}
|
|
759
|
+
async function nativePay(options, ctx) {
|
|
760
|
+
if (!ctx) {
|
|
761
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
762
|
+
}
|
|
763
|
+
if (typeof window === "undefined" || !isCommandAvailable("pay" /* Pay */)) {
|
|
764
|
+
throw new Error(
|
|
765
|
+
"'pay' command is unavailable. Check MiniKit.install() or update the app version"
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
const input = {
|
|
769
|
+
reference: options.reference,
|
|
770
|
+
to: options.to,
|
|
771
|
+
tokens: options.tokens,
|
|
772
|
+
description: options.description,
|
|
773
|
+
network: options.network
|
|
774
|
+
};
|
|
775
|
+
if (!validatePaymentPayload(input)) {
|
|
776
|
+
throw new Error("Invalid payment payload");
|
|
777
|
+
}
|
|
778
|
+
const eventPayload = {
|
|
779
|
+
...input,
|
|
780
|
+
network: "worldchain" /* WorldChain */
|
|
781
|
+
};
|
|
782
|
+
const finalPayload = await new Promise(
|
|
783
|
+
(resolve, reject) => {
|
|
784
|
+
try {
|
|
785
|
+
ctx.events.subscribe("miniapp-payment" /* MiniAppPayment */, (response) => {
|
|
786
|
+
ctx.events.unsubscribe("miniapp-payment" /* MiniAppPayment */);
|
|
787
|
+
resolve(response);
|
|
788
|
+
});
|
|
789
|
+
sendMiniKitEvent({
|
|
790
|
+
command: "pay" /* Pay */,
|
|
791
|
+
version: COMMAND_VERSIONS["pay" /* Pay */],
|
|
792
|
+
payload: eventPayload
|
|
793
|
+
});
|
|
794
|
+
} catch (error) {
|
|
795
|
+
reject(error);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
);
|
|
799
|
+
if (finalPayload.status === "error") {
|
|
800
|
+
throw new PayError(finalPayload.error_code);
|
|
801
|
+
}
|
|
802
|
+
return {
|
|
803
|
+
transactionId: finalPayload.transaction_id,
|
|
804
|
+
reference: finalPayload.reference,
|
|
805
|
+
from: finalPayload.from,
|
|
806
|
+
chain: finalPayload.chain,
|
|
807
|
+
timestamp: finalPayload.timestamp
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// src/commands/request-permission/types.ts
|
|
812
|
+
var RequestPermissionError = class extends Error {
|
|
813
|
+
constructor(error_code) {
|
|
814
|
+
super(`Request permission failed: ${error_code}`);
|
|
815
|
+
this.error_code = error_code;
|
|
816
|
+
this.name = "RequestPermissionError";
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
|
|
820
|
+
// src/commands/request-permission/index.ts
|
|
821
|
+
async function requestPermission(options, ctx) {
|
|
822
|
+
const result = await executeWithFallback({
|
|
823
|
+
command: "request-permission" /* RequestPermission */,
|
|
824
|
+
nativeExecutor: () => nativeRequestPermission(options, ctx),
|
|
825
|
+
customFallback: options.fallback
|
|
826
|
+
});
|
|
827
|
+
if (result.executedWith === "fallback") {
|
|
828
|
+
return { executedWith: "fallback", data: result.data };
|
|
829
|
+
}
|
|
830
|
+
return {
|
|
831
|
+
executedWith: "minikit",
|
|
832
|
+
data: result.data
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
async function nativeRequestPermission(options, ctx) {
|
|
836
|
+
if (!ctx) {
|
|
837
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
838
|
+
}
|
|
839
|
+
if (typeof window === "undefined" || !isCommandAvailable("request-permission" /* RequestPermission */)) {
|
|
840
|
+
throw new Error(
|
|
841
|
+
"'requestPermission' command is unavailable. Check MiniKit.install() or update the app version"
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
const payload = await new Promise(
|
|
845
|
+
(resolve, reject) => {
|
|
846
|
+
try {
|
|
847
|
+
ctx.events.subscribe("miniapp-request-permission" /* MiniAppRequestPermission */, (response) => {
|
|
848
|
+
ctx.events.unsubscribe("miniapp-request-permission" /* MiniAppRequestPermission */);
|
|
849
|
+
resolve(response);
|
|
850
|
+
});
|
|
851
|
+
sendMiniKitEvent({
|
|
852
|
+
command: "request-permission" /* RequestPermission */,
|
|
853
|
+
version: COMMAND_VERSIONS["request-permission" /* RequestPermission */],
|
|
854
|
+
payload: { permission: options.permission }
|
|
855
|
+
});
|
|
856
|
+
} catch (error) {
|
|
857
|
+
reject(error);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
);
|
|
861
|
+
if (payload.status === "error") {
|
|
862
|
+
throw new RequestPermissionError(payload.error_code);
|
|
863
|
+
}
|
|
864
|
+
return payload;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// src/commands/send-haptic-feedback/types.ts
|
|
868
|
+
var SendHapticFeedbackError = class extends Error {
|
|
869
|
+
constructor(error_code) {
|
|
870
|
+
super(`Send haptic feedback failed: ${error_code}`);
|
|
871
|
+
this.error_code = error_code;
|
|
872
|
+
this.name = "SendHapticFeedbackError";
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
|
|
876
|
+
// src/commands/send-haptic-feedback/index.ts
|
|
877
|
+
async function sendHapticFeedback(options, ctx) {
|
|
878
|
+
const result = await executeWithFallback({
|
|
879
|
+
command: "send-haptic-feedback" /* SendHapticFeedback */,
|
|
880
|
+
nativeExecutor: () => nativeSendHapticFeedback(options, ctx),
|
|
881
|
+
customFallback: options.fallback
|
|
882
|
+
});
|
|
883
|
+
if (result.executedWith === "fallback") {
|
|
884
|
+
return { executedWith: "fallback", data: result.data };
|
|
885
|
+
}
|
|
886
|
+
return {
|
|
887
|
+
executedWith: "minikit",
|
|
888
|
+
data: result.data
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
async function nativeSendHapticFeedback(options, ctx) {
|
|
892
|
+
if (!ctx) {
|
|
893
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
894
|
+
}
|
|
895
|
+
if (typeof window === "undefined" || !isCommandAvailable("send-haptic-feedback" /* SendHapticFeedback */)) {
|
|
896
|
+
throw new Error(
|
|
897
|
+
"'sendHapticFeedback' command is unavailable. Check MiniKit.install() or update the app version"
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
const payloadInput = options.hapticsType === "selection-changed" ? { hapticsType: "selection-changed" } : options.hapticsType === "impact" ? {
|
|
901
|
+
hapticsType: "impact",
|
|
902
|
+
style: options.style
|
|
903
|
+
} : {
|
|
904
|
+
hapticsType: "notification",
|
|
905
|
+
style: options.style
|
|
906
|
+
};
|
|
907
|
+
const payload = await new Promise(
|
|
908
|
+
(resolve, reject) => {
|
|
909
|
+
try {
|
|
910
|
+
ctx.events.subscribe("miniapp-send-haptic-feedback" /* MiniAppSendHapticFeedback */, (response) => {
|
|
911
|
+
ctx.events.unsubscribe("miniapp-send-haptic-feedback" /* MiniAppSendHapticFeedback */);
|
|
912
|
+
resolve(response);
|
|
913
|
+
});
|
|
914
|
+
sendMiniKitEvent({
|
|
915
|
+
command: "send-haptic-feedback" /* SendHapticFeedback */,
|
|
916
|
+
version: COMMAND_VERSIONS["send-haptic-feedback" /* SendHapticFeedback */],
|
|
917
|
+
payload: payloadInput
|
|
918
|
+
});
|
|
919
|
+
} catch (error) {
|
|
920
|
+
reject(error);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
);
|
|
924
|
+
if (payload.status === "error") {
|
|
925
|
+
throw new SendHapticFeedbackError(payload.error_code);
|
|
926
|
+
}
|
|
927
|
+
return payload;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
// src/commands/send-transaction/types.ts
|
|
931
|
+
var SendTransactionError = class extends Error {
|
|
932
|
+
constructor(code, details) {
|
|
933
|
+
super(`Transaction failed: ${code}`);
|
|
934
|
+
this.name = "SendTransactionError";
|
|
935
|
+
this.code = code;
|
|
936
|
+
this.details = details;
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
|
|
940
|
+
// src/commands/send-transaction/validate.ts
|
|
941
|
+
var isValidHex = (str) => {
|
|
942
|
+
return /^0x[0-9A-Fa-f]+$/.test(str);
|
|
943
|
+
};
|
|
944
|
+
var processPayload = (payload) => {
|
|
945
|
+
if (typeof payload === "boolean" || typeof payload === "string" || payload === null || payload === void 0) {
|
|
946
|
+
return payload;
|
|
947
|
+
}
|
|
948
|
+
if (typeof payload === "number" || typeof payload === "bigint") {
|
|
949
|
+
return String(payload);
|
|
950
|
+
}
|
|
951
|
+
if (Array.isArray(payload)) {
|
|
952
|
+
return payload.map((value) => processPayload(value));
|
|
953
|
+
}
|
|
954
|
+
if (typeof payload === "object") {
|
|
955
|
+
const result = { ...payload };
|
|
956
|
+
if ("chainId" in result && result.chainId !== void 0) {
|
|
957
|
+
if (typeof result.chainId === "string") {
|
|
958
|
+
const parsed = Number(result.chainId);
|
|
959
|
+
if (Number.isFinite(parsed)) {
|
|
960
|
+
result.chainId = parsed;
|
|
961
|
+
}
|
|
962
|
+
} else if (typeof result.chainId === "bigint") {
|
|
963
|
+
const parsed = Number(result.chainId);
|
|
964
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
965
|
+
throw new Error(`Invalid chainId: ${String(result.chainId)}`);
|
|
966
|
+
}
|
|
967
|
+
result.chainId = parsed;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
if ("value" in result && result.value !== void 0) {
|
|
971
|
+
if (typeof result.value !== "string") {
|
|
972
|
+
result.value = String(result.value);
|
|
973
|
+
}
|
|
974
|
+
if (!isValidHex(result.value)) {
|
|
975
|
+
console.error(
|
|
976
|
+
"Transaction value must be a valid hex string",
|
|
977
|
+
result.value
|
|
978
|
+
);
|
|
979
|
+
throw new Error(
|
|
980
|
+
`Transaction value must be a valid hex string: ${result.value}`
|
|
981
|
+
);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
for (const key in result) {
|
|
985
|
+
if (Object.prototype.hasOwnProperty.call(result, key)) {
|
|
986
|
+
if (key === "chainId") continue;
|
|
987
|
+
result[key] = processPayload(result[key]);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
return result;
|
|
991
|
+
}
|
|
992
|
+
return payload;
|
|
993
|
+
};
|
|
994
|
+
var validateSendTransactionPayload = (payload) => {
|
|
995
|
+
return processPayload(payload);
|
|
996
|
+
};
|
|
997
|
+
|
|
998
|
+
// src/commands/send-transaction/index.ts
|
|
999
|
+
var WORLD_CHAIN_ID = 480;
|
|
1000
|
+
var WAGMI_MULTI_TX_ERROR_MESSAGE = "Wagmi fallback does not support multi-transaction execution. Pass a single transaction, run inside World App for batching, or provide a custom fallback.";
|
|
1001
|
+
function resolveChainId(options) {
|
|
1002
|
+
return options.chainId;
|
|
1003
|
+
}
|
|
1004
|
+
function resolveTransactions(options) {
|
|
1005
|
+
if (options.transactions.length === 0) {
|
|
1006
|
+
throw new SendTransactionError("input_error" /* InputError */, {
|
|
1007
|
+
reason: "At least one transaction is required. Use `transactions: [{ to, data, value }]`."
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
return options.transactions;
|
|
1011
|
+
}
|
|
1012
|
+
function normalizeSendTransactionOptions(options) {
|
|
1013
|
+
const chainId = resolveChainId(options);
|
|
1014
|
+
if (chainId !== WORLD_CHAIN_ID) {
|
|
1015
|
+
throw new SendTransactionError("invalid_operation" /* InvalidOperation */, {
|
|
1016
|
+
reason: `World App only supports World Chain (chainId: ${WORLD_CHAIN_ID})`
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
return {
|
|
1020
|
+
transactions: resolveTransactions(options),
|
|
1021
|
+
chainId
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
async function sendTransaction(options, ctx) {
|
|
1025
|
+
const normalizedOptions = normalizeSendTransactionOptions(options);
|
|
1026
|
+
const fallbackAdapter = getFallbackAdapter();
|
|
1027
|
+
const isWagmiFallbackPath = !isInWorldApp() && Boolean(fallbackAdapter?.sendTransaction);
|
|
1028
|
+
if (isWagmiFallbackPath && normalizedOptions.transactions.length > 1 && !options.fallback) {
|
|
1029
|
+
throw new SendTransactionError("invalid_operation" /* InvalidOperation */, {
|
|
1030
|
+
reason: WAGMI_MULTI_TX_ERROR_MESSAGE
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
const result = await executeWithFallback({
|
|
1034
|
+
command: "send-transaction" /* SendTransaction */,
|
|
1035
|
+
nativeExecutor: () => nativeSendTransaction(normalizedOptions, ctx),
|
|
1036
|
+
wagmiFallback: fallbackAdapter?.sendTransaction ? () => adapterSendTransactionFallback(normalizedOptions) : void 0,
|
|
1037
|
+
customFallback: options.fallback
|
|
1038
|
+
});
|
|
1039
|
+
if (result.executedWith === "fallback") {
|
|
1040
|
+
return { executedWith: "fallback", data: result.data };
|
|
1041
|
+
}
|
|
1042
|
+
if (result.executedWith === "wagmi") {
|
|
1043
|
+
return {
|
|
1044
|
+
executedWith: "wagmi",
|
|
1045
|
+
data: result.data
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
return {
|
|
1049
|
+
executedWith: "minikit",
|
|
1050
|
+
data: result.data
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
async function nativeSendTransaction(options, ctx) {
|
|
1054
|
+
if (!ctx) {
|
|
1055
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
1056
|
+
}
|
|
1057
|
+
if (typeof window === "undefined" || !isCommandAvailable("send-transaction" /* SendTransaction */)) {
|
|
1058
|
+
throw new Error(
|
|
1059
|
+
"'sendTransaction' command is unavailable. Check MiniKit.install() or update the app version"
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
if (options.chainId !== WORLD_CHAIN_ID) {
|
|
1063
|
+
throw new Error(
|
|
1064
|
+
`World App only supports World Chain (chainId: ${WORLD_CHAIN_ID})`
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
const commandInput = window.WorldApp?.supported_commands.find(
|
|
1068
|
+
(command) => command.name === "send-transaction" /* SendTransaction */
|
|
1069
|
+
);
|
|
1070
|
+
if (commandInput && !commandInput.supported_versions.includes(
|
|
1071
|
+
COMMAND_VERSIONS["send-transaction" /* SendTransaction */]
|
|
1072
|
+
)) {
|
|
1073
|
+
throw new CommandUnavailableError("send-transaction" /* SendTransaction */, "oldAppVersion");
|
|
1074
|
+
}
|
|
1075
|
+
const input = {
|
|
1076
|
+
transactions: options.transactions,
|
|
1077
|
+
chainId: options.chainId
|
|
1078
|
+
};
|
|
1079
|
+
const validatedPayload = validateSendTransactionPayload(input);
|
|
1080
|
+
const finalPayload = await new Promise(
|
|
1081
|
+
(resolve, reject) => {
|
|
1082
|
+
try {
|
|
1083
|
+
ctx.events.subscribe("miniapp-send-transaction" /* MiniAppSendTransaction */, (response) => {
|
|
1084
|
+
ctx.events.unsubscribe("miniapp-send-transaction" /* MiniAppSendTransaction */);
|
|
1085
|
+
resolve(response);
|
|
1086
|
+
});
|
|
1087
|
+
sendMiniKitEvent({
|
|
1088
|
+
command: "send-transaction" /* SendTransaction */,
|
|
1089
|
+
version: COMMAND_VERSIONS["send-transaction" /* SendTransaction */],
|
|
1090
|
+
payload: validatedPayload
|
|
1091
|
+
});
|
|
1092
|
+
} catch (error) {
|
|
1093
|
+
reject(error);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
);
|
|
1097
|
+
if (finalPayload.status === "error") {
|
|
1098
|
+
throw new SendTransactionError(
|
|
1099
|
+
finalPayload.error_code,
|
|
1100
|
+
finalPayload.details
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
1103
|
+
const successPayload = finalPayload;
|
|
1104
|
+
return {
|
|
1105
|
+
userOpHash: String(successPayload.userOpHash ?? ""),
|
|
1106
|
+
status: finalPayload.status,
|
|
1107
|
+
version: finalPayload.version,
|
|
1108
|
+
from: String(successPayload.from ?? ""),
|
|
1109
|
+
timestamp: String(successPayload.timestamp ?? (/* @__PURE__ */ new Date()).toISOString())
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
async function adapterSendTransactionFallback(options) {
|
|
1113
|
+
if (options.transactions.length > 1) {
|
|
1114
|
+
throw new Error(WAGMI_MULTI_TX_ERROR_MESSAGE);
|
|
1115
|
+
}
|
|
1116
|
+
const firstTransaction = options.transactions[0];
|
|
1117
|
+
if (!firstTransaction) {
|
|
1118
|
+
throw new Error("At least one transaction is required");
|
|
1119
|
+
}
|
|
1120
|
+
const fallbackAdapter = getFallbackAdapter();
|
|
1121
|
+
if (!fallbackAdapter?.sendTransaction) {
|
|
1122
|
+
throw new Error("Fallback adapter is not registered.");
|
|
1123
|
+
}
|
|
1124
|
+
const result = await fallbackAdapter.sendTransaction({
|
|
1125
|
+
transaction: {
|
|
1126
|
+
address: firstTransaction.to,
|
|
1127
|
+
data: firstTransaction.data,
|
|
1128
|
+
value: firstTransaction.value
|
|
1129
|
+
},
|
|
1130
|
+
chainId: options.chainId
|
|
1131
|
+
});
|
|
1132
|
+
return {
|
|
1133
|
+
userOpHash: result.transactionHash,
|
|
1134
|
+
status: "success",
|
|
1135
|
+
version: COMMAND_VERSIONS["send-transaction" /* SendTransaction */],
|
|
1136
|
+
from: "",
|
|
1137
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
// src/commands/share/format.ts
|
|
1142
|
+
var MAX_FILES = 10;
|
|
1143
|
+
var MAX_TOTAL_SIZE_MB = 50;
|
|
1144
|
+
var MAX_TOTAL_SIZE_BYTES = MAX_TOTAL_SIZE_MB * 1024 * 1024;
|
|
1145
|
+
var processFile = async (file) => {
|
|
1146
|
+
const buffer = await file.arrayBuffer();
|
|
1147
|
+
const uint8Array = new Uint8Array(buffer);
|
|
1148
|
+
let binaryString = "";
|
|
1149
|
+
const K_CHUNK_SIZE = 32768;
|
|
1150
|
+
for (let i = 0; i < uint8Array.length; i += K_CHUNK_SIZE) {
|
|
1151
|
+
const chunk = uint8Array.subarray(
|
|
1152
|
+
i,
|
|
1153
|
+
Math.min(i + K_CHUNK_SIZE, uint8Array.length)
|
|
1154
|
+
);
|
|
1155
|
+
binaryString += String.fromCharCode.apply(
|
|
1156
|
+
null,
|
|
1157
|
+
Array.from(chunk)
|
|
1158
|
+
// Convert Uint8Array chunk to number[]
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
const base64Data = btoa(binaryString);
|
|
1162
|
+
return {
|
|
1163
|
+
name: file.name,
|
|
1164
|
+
type: file.type,
|
|
1165
|
+
data: base64Data
|
|
1166
|
+
};
|
|
1167
|
+
};
|
|
1168
|
+
var formatShareInput = async (input) => {
|
|
1169
|
+
if (!input.files) {
|
|
1170
|
+
return {
|
|
1171
|
+
title: input.title,
|
|
1172
|
+
text: input.text,
|
|
1173
|
+
url: input.url
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
if (!Array.isArray(input.files)) {
|
|
1177
|
+
throw new Error('The "files" property must be an array.');
|
|
1178
|
+
}
|
|
1179
|
+
if (input.files.length === 0) {
|
|
1180
|
+
} else {
|
|
1181
|
+
if (input.files.length > MAX_FILES) {
|
|
1182
|
+
throw new Error(`Cannot share more than ${MAX_FILES} files.`);
|
|
1183
|
+
}
|
|
1184
|
+
let totalSize = 0;
|
|
1185
|
+
for (const file of input.files) {
|
|
1186
|
+
if (!(file instanceof File)) {
|
|
1187
|
+
throw new Error(
|
|
1188
|
+
`Each item in the 'files' array must be a File object. Received: ${typeof file}`
|
|
1189
|
+
);
|
|
1190
|
+
}
|
|
1191
|
+
totalSize += file.size;
|
|
1192
|
+
}
|
|
1193
|
+
if (totalSize > MAX_TOTAL_SIZE_BYTES) {
|
|
1194
|
+
throw new Error(`Total file size cannot exceed ${MAX_TOTAL_SIZE_MB}MB.`);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
const fileProcessingPromises = input.files.map((file) => processFile(file));
|
|
1198
|
+
const processedFiles = await Promise.all(fileProcessingPromises);
|
|
1199
|
+
return {
|
|
1200
|
+
files: processedFiles,
|
|
1201
|
+
title: input.title,
|
|
1202
|
+
text: input.text,
|
|
1203
|
+
url: input.url
|
|
1204
|
+
};
|
|
1205
|
+
};
|
|
1206
|
+
|
|
1207
|
+
// src/commands/share/types.ts
|
|
1208
|
+
var ShareError = class extends Error {
|
|
1209
|
+
constructor(error_code) {
|
|
1210
|
+
super(`Share failed: ${error_code}`);
|
|
1211
|
+
this.error_code = error_code;
|
|
1212
|
+
this.name = "ShareError";
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
|
|
1216
|
+
// src/commands/share/index.ts
|
|
1217
|
+
async function share(options, ctx) {
|
|
1218
|
+
const result = await executeWithFallback({
|
|
1219
|
+
command: "share" /* Share */,
|
|
1220
|
+
nativeExecutor: () => nativeShare(options, ctx),
|
|
1221
|
+
customFallback: options.fallback
|
|
1222
|
+
});
|
|
1223
|
+
if (result.executedWith === "fallback") {
|
|
1224
|
+
return {
|
|
1225
|
+
executedWith: "fallback",
|
|
1226
|
+
data: result.data
|
|
1227
|
+
};
|
|
1228
|
+
}
|
|
1229
|
+
return {
|
|
1230
|
+
executedWith: "minikit",
|
|
1231
|
+
data: result.data
|
|
1232
|
+
};
|
|
1233
|
+
}
|
|
1234
|
+
async function nativeShare(options, ctx) {
|
|
1235
|
+
if (!ctx) {
|
|
1236
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
1237
|
+
}
|
|
1238
|
+
if (typeof window === "undefined" || !isCommandAvailable("share" /* Share */)) {
|
|
1239
|
+
throw new Error(
|
|
1240
|
+
"'share' command is unavailable. Check MiniKit.install() or update the app version"
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
1243
|
+
const payloadInput = {
|
|
1244
|
+
files: options.files,
|
|
1245
|
+
title: options.title,
|
|
1246
|
+
text: options.text,
|
|
1247
|
+
url: options.url
|
|
1248
|
+
};
|
|
1249
|
+
if (ctx.state.deviceProperties.deviceOS === "ios" && typeof navigator !== "undefined") {
|
|
1250
|
+
sendMiniKitEvent({
|
|
1251
|
+
command: "share" /* Share */,
|
|
1252
|
+
version: COMMAND_VERSIONS["share" /* Share */],
|
|
1253
|
+
payload: payloadInput
|
|
1254
|
+
});
|
|
1255
|
+
await navigator.share(payloadInput);
|
|
1256
|
+
return {
|
|
1257
|
+
status: "success",
|
|
1258
|
+
version: COMMAND_VERSIONS["share" /* Share */],
|
|
1259
|
+
shared_files_count: payloadInput.files?.length ?? 0,
|
|
1260
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
const formattedPayload = await formatShareInput(payloadInput);
|
|
1264
|
+
const payload = await new Promise((resolve, reject) => {
|
|
1265
|
+
try {
|
|
1266
|
+
ctx.events.subscribe("miniapp-share" /* MiniAppShare */, (response) => {
|
|
1267
|
+
ctx.events.unsubscribe("miniapp-share" /* MiniAppShare */);
|
|
1268
|
+
resolve(response);
|
|
1269
|
+
});
|
|
1270
|
+
sendMiniKitEvent({
|
|
1271
|
+
command: "share" /* Share */,
|
|
1272
|
+
version: COMMAND_VERSIONS["share" /* Share */],
|
|
1273
|
+
payload: formattedPayload
|
|
1274
|
+
});
|
|
1275
|
+
} catch (error) {
|
|
1276
|
+
reject(error);
|
|
1277
|
+
}
|
|
1278
|
+
});
|
|
1279
|
+
if (payload.status === "error") {
|
|
1280
|
+
throw new ShareError(payload.error_code);
|
|
1281
|
+
}
|
|
1282
|
+
return payload;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
// src/commands/share-contacts/types.ts
|
|
1286
|
+
var ShareContactsError = class extends Error {
|
|
1287
|
+
constructor(code) {
|
|
1288
|
+
super(`Share contacts failed: ${code}`);
|
|
1289
|
+
this.name = "ShareContactsError";
|
|
1290
|
+
this.code = code;
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1293
|
+
|
|
1294
|
+
// src/commands/share-contacts/index.ts
|
|
1295
|
+
async function shareContacts(options, ctx) {
|
|
1296
|
+
const resolvedOptions = options ?? {};
|
|
1297
|
+
const result = await executeWithFallback({
|
|
1298
|
+
command: "share-contacts" /* ShareContacts */,
|
|
1299
|
+
nativeExecutor: () => nativeShareContacts(resolvedOptions, ctx),
|
|
1300
|
+
// No Wagmi fallback - contacts is native only
|
|
1301
|
+
customFallback: resolvedOptions.fallback
|
|
1302
|
+
});
|
|
1303
|
+
if (result.executedWith === "fallback") {
|
|
1304
|
+
return { executedWith: "fallback", data: result.data };
|
|
1305
|
+
}
|
|
1306
|
+
return { executedWith: "minikit", data: result.data };
|
|
1307
|
+
}
|
|
1308
|
+
async function nativeShareContacts(options, ctx) {
|
|
1309
|
+
if (!ctx) {
|
|
1310
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
1311
|
+
}
|
|
1312
|
+
if (typeof window === "undefined" || !isCommandAvailable("share-contacts" /* ShareContacts */)) {
|
|
1313
|
+
throw new Error(
|
|
1314
|
+
"'shareContacts' command is unavailable. Check MiniKit.install() or update the app version"
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
const payload = {
|
|
1318
|
+
isMultiSelectEnabled: options.isMultiSelectEnabled ?? false,
|
|
1319
|
+
inviteMessage: options.inviteMessage
|
|
1320
|
+
};
|
|
1321
|
+
const finalPayload = await new Promise(
|
|
1322
|
+
(resolve, reject) => {
|
|
1323
|
+
try {
|
|
1324
|
+
ctx.events.subscribe("miniapp-share-contacts" /* MiniAppShareContacts */, (response) => {
|
|
1325
|
+
ctx.events.unsubscribe("miniapp-share-contacts" /* MiniAppShareContacts */);
|
|
1326
|
+
resolve(response);
|
|
1327
|
+
});
|
|
1328
|
+
sendMiniKitEvent({
|
|
1329
|
+
command: "share-contacts" /* ShareContacts */,
|
|
1330
|
+
version: COMMAND_VERSIONS["share-contacts" /* ShareContacts */],
|
|
1331
|
+
payload
|
|
1332
|
+
});
|
|
1333
|
+
} catch (error) {
|
|
1334
|
+
reject(error);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
);
|
|
1338
|
+
if (finalPayload.status === "error") {
|
|
1339
|
+
throw new ShareContactsError(finalPayload.error_code);
|
|
1340
|
+
}
|
|
1341
|
+
return {
|
|
1342
|
+
contacts: finalPayload.contacts,
|
|
1343
|
+
timestamp: finalPayload.timestamp
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
// src/commands/sign-message/types.ts
|
|
1348
|
+
var SignMessageError = class extends Error {
|
|
1349
|
+
constructor(error_code) {
|
|
1350
|
+
super(`Sign message failed: ${error_code}`);
|
|
1351
|
+
this.error_code = error_code;
|
|
1352
|
+
this.name = "SignMessageError";
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1355
|
+
|
|
1356
|
+
// src/commands/sign-message/index.ts
|
|
1357
|
+
async function signMessage(options, ctx) {
|
|
1358
|
+
const fallbackAdapter = getFallbackAdapter();
|
|
1359
|
+
const result = await executeWithFallback({
|
|
1360
|
+
command: "sign-message" /* SignMessage */,
|
|
1361
|
+
nativeExecutor: () => nativeSignMessage(options, ctx),
|
|
1362
|
+
wagmiFallback: fallbackAdapter?.signMessage ? () => fallbackAdapter.signMessage({
|
|
1363
|
+
message: options.message
|
|
1364
|
+
}) : void 0,
|
|
1365
|
+
customFallback: options.fallback
|
|
1366
|
+
});
|
|
1367
|
+
if (result.executedWith === "fallback") {
|
|
1368
|
+
return { executedWith: "fallback", data: result.data };
|
|
1369
|
+
}
|
|
1370
|
+
if (result.executedWith === "wagmi") {
|
|
1371
|
+
return {
|
|
1372
|
+
executedWith: "wagmi",
|
|
1373
|
+
data: result.data
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
return {
|
|
1377
|
+
executedWith: "minikit",
|
|
1378
|
+
data: result.data
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
1381
|
+
async function nativeSignMessage(options, ctx) {
|
|
1382
|
+
if (!ctx) {
|
|
1383
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
1384
|
+
}
|
|
1385
|
+
if (typeof window === "undefined" || !isCommandAvailable("sign-message" /* SignMessage */)) {
|
|
1386
|
+
throw new Error(
|
|
1387
|
+
"'signMessage' command is unavailable. Check MiniKit.install() or update the app version"
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
const payload = await new Promise(
|
|
1391
|
+
(resolve, reject) => {
|
|
1392
|
+
try {
|
|
1393
|
+
ctx.events.subscribe("miniapp-sign-message" /* MiniAppSignMessage */, (response) => {
|
|
1394
|
+
ctx.events.unsubscribe("miniapp-sign-message" /* MiniAppSignMessage */);
|
|
1395
|
+
resolve(response);
|
|
1396
|
+
});
|
|
1397
|
+
sendMiniKitEvent({
|
|
1398
|
+
command: "sign-message" /* SignMessage */,
|
|
1399
|
+
version: COMMAND_VERSIONS["sign-message" /* SignMessage */],
|
|
1400
|
+
payload: { message: options.message }
|
|
1401
|
+
});
|
|
1402
|
+
} catch (error) {
|
|
1403
|
+
reject(error);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
);
|
|
1407
|
+
if (payload.status === "error") {
|
|
1408
|
+
throw new SignMessageError(payload.error_code);
|
|
1409
|
+
}
|
|
1410
|
+
return payload;
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
// src/commands/sign-typed-data/types.ts
|
|
1414
|
+
var SignTypedDataError = class extends Error {
|
|
1415
|
+
constructor(error_code) {
|
|
1416
|
+
super(`Sign typed data failed: ${error_code}`);
|
|
1417
|
+
this.error_code = error_code;
|
|
1418
|
+
this.name = "SignTypedDataError";
|
|
1419
|
+
}
|
|
1420
|
+
};
|
|
1421
|
+
|
|
1422
|
+
// src/commands/sign-typed-data/index.ts
|
|
1423
|
+
async function signTypedData(options, ctx) {
|
|
1424
|
+
const fallbackAdapter = getFallbackAdapter();
|
|
1425
|
+
const result = await executeWithFallback({
|
|
1426
|
+
command: "sign-typed-data" /* SignTypedData */,
|
|
1427
|
+
nativeExecutor: () => nativeSignTypedData(options, ctx),
|
|
1428
|
+
wagmiFallback: fallbackAdapter?.signTypedData ? () => fallbackAdapter.signTypedData({
|
|
1429
|
+
types: options.types,
|
|
1430
|
+
primaryType: options.primaryType,
|
|
1431
|
+
message: options.message,
|
|
1432
|
+
domain: options.domain,
|
|
1433
|
+
chainId: options.chainId
|
|
1434
|
+
}) : void 0,
|
|
1435
|
+
customFallback: options.fallback
|
|
1436
|
+
});
|
|
1437
|
+
if (result.executedWith === "fallback") {
|
|
1438
|
+
return { executedWith: "fallback", data: result.data };
|
|
1439
|
+
}
|
|
1440
|
+
if (result.executedWith === "wagmi") {
|
|
1441
|
+
return {
|
|
1442
|
+
executedWith: "wagmi",
|
|
1443
|
+
data: result.data
|
|
1444
|
+
};
|
|
1445
|
+
}
|
|
1446
|
+
return {
|
|
1447
|
+
executedWith: "minikit",
|
|
1448
|
+
data: result.data
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
async function nativeSignTypedData(options, ctx) {
|
|
1452
|
+
if (!ctx) {
|
|
1453
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
1454
|
+
}
|
|
1455
|
+
if (typeof window === "undefined" || !isCommandAvailable("sign-typed-data" /* SignTypedData */)) {
|
|
1456
|
+
throw new Error(
|
|
1457
|
+
"'signTypedData' command is unavailable. Check MiniKit.install() or update the app version"
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1460
|
+
const payloadInput = {
|
|
1461
|
+
types: options.types,
|
|
1462
|
+
primaryType: options.primaryType,
|
|
1463
|
+
message: options.message,
|
|
1464
|
+
domain: options.domain,
|
|
1465
|
+
chainId: options.chainId ?? 480
|
|
1466
|
+
};
|
|
1467
|
+
const payload = await new Promise(
|
|
1468
|
+
(resolve, reject) => {
|
|
1469
|
+
try {
|
|
1470
|
+
ctx.events.subscribe("miniapp-sign-typed-data" /* MiniAppSignTypedData */, (response) => {
|
|
1471
|
+
ctx.events.unsubscribe("miniapp-sign-typed-data" /* MiniAppSignTypedData */);
|
|
1472
|
+
resolve(response);
|
|
1473
|
+
});
|
|
1474
|
+
sendMiniKitEvent({
|
|
1475
|
+
command: "sign-typed-data" /* SignTypedData */,
|
|
1476
|
+
version: COMMAND_VERSIONS["sign-typed-data" /* SignTypedData */],
|
|
1477
|
+
payload: payloadInput
|
|
1478
|
+
});
|
|
1479
|
+
} catch (error) {
|
|
1480
|
+
reject(error);
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
);
|
|
1484
|
+
if (payload.status === "error") {
|
|
1485
|
+
throw new SignTypedDataError(payload.error_code);
|
|
1486
|
+
}
|
|
1487
|
+
return payload;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
// src/commands/wallet-auth/siwe.ts
|
|
1491
|
+
var import_viem = require("viem");
|
|
1492
|
+
var import_chains = require("viem/chains");
|
|
1493
|
+
var generateSiweMessage = (siweMessageData) => {
|
|
1494
|
+
let siweMessage = "";
|
|
1495
|
+
if (siweMessageData.scheme) {
|
|
1496
|
+
siweMessage += `${siweMessageData.scheme}://${siweMessageData.domain} wants you to sign in with your Ethereum account:
|
|
1497
|
+
`;
|
|
1498
|
+
} else {
|
|
1499
|
+
siweMessage += `${siweMessageData.domain} wants you to sign in with your Ethereum account:
|
|
1500
|
+
`;
|
|
1501
|
+
}
|
|
1502
|
+
if (siweMessageData.address) {
|
|
1503
|
+
siweMessage += `${siweMessageData.address}
|
|
1504
|
+
`;
|
|
1505
|
+
} else {
|
|
1506
|
+
siweMessage += "{address}\n";
|
|
1507
|
+
}
|
|
1508
|
+
siweMessage += "\n";
|
|
1509
|
+
if (siweMessageData.statement) {
|
|
1510
|
+
siweMessage += `${siweMessageData.statement}
|
|
1511
|
+
`;
|
|
1512
|
+
}
|
|
1513
|
+
siweMessage += "\n";
|
|
1514
|
+
siweMessage += `URI: ${siweMessageData.uri}
|
|
1515
|
+
`;
|
|
1516
|
+
siweMessage += `Version: ${siweMessageData.version}
|
|
1517
|
+
`;
|
|
1518
|
+
siweMessage += `Chain ID: ${siweMessageData.chain_id}
|
|
1519
|
+
`;
|
|
1520
|
+
siweMessage += `Nonce: ${siweMessageData.nonce}
|
|
1521
|
+
`;
|
|
1522
|
+
siweMessage += `Issued At: ${siweMessageData.issued_at}
|
|
1523
|
+
`;
|
|
1524
|
+
if (siweMessageData.expiration_time) {
|
|
1525
|
+
siweMessage += `Expiration Time: ${siweMessageData.expiration_time}
|
|
1526
|
+
`;
|
|
1527
|
+
}
|
|
1528
|
+
if (siweMessageData.not_before) {
|
|
1529
|
+
siweMessage += `Not Before: ${siweMessageData.not_before}
|
|
1530
|
+
`;
|
|
1531
|
+
}
|
|
1532
|
+
if (siweMessageData.request_id) {
|
|
1533
|
+
siweMessage += `Request ID: ${siweMessageData.request_id}
|
|
1534
|
+
`;
|
|
1535
|
+
}
|
|
1536
|
+
return siweMessage;
|
|
1537
|
+
};
|
|
1538
|
+
|
|
1539
|
+
// src/commands/wallet-auth/types.ts
|
|
1540
|
+
var WalletAuthError = class extends Error {
|
|
1541
|
+
constructor(code, details) {
|
|
1542
|
+
super(details || `Wallet auth failed: ${code}`);
|
|
1543
|
+
this.name = "WalletAuthError";
|
|
1544
|
+
this.code = code;
|
|
1545
|
+
this.details = details;
|
|
1546
|
+
}
|
|
1547
|
+
};
|
|
1548
|
+
|
|
1549
|
+
// src/commands/wallet-auth/validate.ts
|
|
1550
|
+
var SIWE_NONCE_REGEX2 = /^[a-zA-Z0-9]+$/;
|
|
1551
|
+
var validateWalletAuthCommandInput = (params) => {
|
|
1552
|
+
if (!params.nonce) {
|
|
1553
|
+
return { valid: false, message: "'nonce' is required" };
|
|
1554
|
+
}
|
|
1555
|
+
if (params.nonce.length < 8) {
|
|
1556
|
+
return { valid: false, message: "'nonce' must be at least 8 characters" };
|
|
1557
|
+
}
|
|
1558
|
+
if (!SIWE_NONCE_REGEX2.test(params.nonce)) {
|
|
1559
|
+
return {
|
|
1560
|
+
valid: false,
|
|
1561
|
+
message: "'nonce' must be alphanumeric (letters and numbers only)"
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
if (params.statement && params.statement.includes("\n")) {
|
|
1565
|
+
return { valid: false, message: "'statement' must not contain newlines" };
|
|
1566
|
+
}
|
|
1567
|
+
if (params.expirationTime && new Date(params.expirationTime) < /* @__PURE__ */ new Date()) {
|
|
1568
|
+
return { valid: false, message: "'expirationTime' must be in the future" };
|
|
1569
|
+
}
|
|
1570
|
+
if (params.expirationTime && new Date(params.expirationTime) > new Date(Date.now() + 7 * 24 * 60 * 60 * 1e3)) {
|
|
1571
|
+
return { valid: false, message: "'expirationTime' must be within 7 days" };
|
|
1572
|
+
}
|
|
1573
|
+
if (params.notBefore && new Date(params.notBefore) > new Date(Date.now() + 7 * 24 * 60 * 60 * 1e3)) {
|
|
1574
|
+
return { valid: false, message: "'notBefore' must be within 7 days" };
|
|
1575
|
+
}
|
|
1576
|
+
return { valid: true };
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1579
|
+
// src/commands/wallet-auth/index.ts
|
|
1580
|
+
async function walletAuth(options, ctx) {
|
|
1581
|
+
const fallbackAdapter = getFallbackAdapter();
|
|
1582
|
+
const result = await executeWithFallback({
|
|
1583
|
+
command: "wallet-auth" /* WalletAuth */,
|
|
1584
|
+
nativeExecutor: () => nativeWalletAuth(options, ctx),
|
|
1585
|
+
wagmiFallback: fallbackAdapter?.walletAuth ? () => fallbackAdapter.walletAuth({
|
|
1586
|
+
nonce: options.nonce,
|
|
1587
|
+
statement: options.statement,
|
|
1588
|
+
expirationTime: options.expirationTime
|
|
1589
|
+
}) : void 0,
|
|
1590
|
+
customFallback: options.fallback
|
|
1591
|
+
});
|
|
1592
|
+
if (result.executedWith === "fallback") {
|
|
1593
|
+
return { executedWith: "fallback", data: result.data };
|
|
1594
|
+
}
|
|
1595
|
+
if (result.executedWith === "wagmi") {
|
|
1596
|
+
return {
|
|
1597
|
+
executedWith: "wagmi",
|
|
1598
|
+
data: result.data
|
|
1599
|
+
};
|
|
1600
|
+
}
|
|
1601
|
+
return {
|
|
1602
|
+
executedWith: "minikit",
|
|
1603
|
+
data: result.data
|
|
1604
|
+
};
|
|
1605
|
+
}
|
|
1606
|
+
async function nativeWalletAuth(options, ctx) {
|
|
1607
|
+
if (!ctx) {
|
|
1608
|
+
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
|
|
1609
|
+
}
|
|
1610
|
+
if (typeof window === "undefined" || !isCommandAvailable("wallet-auth" /* WalletAuth */)) {
|
|
1611
|
+
throw new Error(
|
|
1612
|
+
"'walletAuth' command is unavailable. Check MiniKit.install() or update the app version"
|
|
1613
|
+
);
|
|
1614
|
+
}
|
|
1615
|
+
const input = {
|
|
1616
|
+
nonce: options.nonce,
|
|
1617
|
+
statement: options.statement,
|
|
1618
|
+
requestId: options.requestId,
|
|
1619
|
+
expirationTime: options.expirationTime,
|
|
1620
|
+
notBefore: options.notBefore
|
|
1621
|
+
};
|
|
1622
|
+
const validationResult = validateWalletAuthCommandInput(input);
|
|
1623
|
+
if (!validationResult.valid) {
|
|
1624
|
+
throw new Error(`Invalid wallet auth input: ${validationResult.message}`);
|
|
1625
|
+
}
|
|
1626
|
+
let protocol;
|
|
1627
|
+
try {
|
|
1628
|
+
const currentUrl = new URL(window.location.href);
|
|
1629
|
+
protocol = currentUrl.protocol.split(":")[0];
|
|
1630
|
+
} catch (error) {
|
|
1631
|
+
throw new Error("Failed to get current URL");
|
|
1632
|
+
}
|
|
1633
|
+
const siweMessage = generateSiweMessage({
|
|
1634
|
+
scheme: protocol,
|
|
1635
|
+
domain: window.location.host,
|
|
1636
|
+
statement: input.statement ?? void 0,
|
|
1637
|
+
uri: window.location.href,
|
|
1638
|
+
version: "1",
|
|
1639
|
+
chain_id: 480,
|
|
1640
|
+
nonce: input.nonce,
|
|
1641
|
+
issued_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1642
|
+
expiration_time: input.expirationTime?.toISOString() ?? void 0,
|
|
1643
|
+
not_before: input.notBefore?.toISOString() ?? void 0,
|
|
1644
|
+
request_id: input.requestId ?? void 0
|
|
1645
|
+
});
|
|
1646
|
+
const walletAuthPayload = { siweMessage };
|
|
1647
|
+
const worldAppVersion = ctx.state.deviceProperties.worldAppVersion;
|
|
1648
|
+
const walletAuthVersion = worldAppVersion && worldAppVersion > 2087900 ? COMMAND_VERSIONS["wallet-auth" /* WalletAuth */] : 1;
|
|
1649
|
+
const finalPayload = await new Promise(
|
|
1650
|
+
(resolve, reject) => {
|
|
1651
|
+
try {
|
|
1652
|
+
ctx.events.subscribe("miniapp-wallet-auth" /* MiniAppWalletAuth */, (response) => {
|
|
1653
|
+
ctx.events.unsubscribe("miniapp-wallet-auth" /* MiniAppWalletAuth */);
|
|
1654
|
+
resolve(response);
|
|
1655
|
+
});
|
|
1656
|
+
sendMiniKitEvent({
|
|
1657
|
+
command: "wallet-auth" /* WalletAuth */,
|
|
1658
|
+
version: walletAuthVersion,
|
|
1659
|
+
payload: walletAuthPayload
|
|
1660
|
+
});
|
|
1661
|
+
} catch (error) {
|
|
1662
|
+
reject(error);
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
);
|
|
1666
|
+
if (finalPayload.status === "error") {
|
|
1667
|
+
throw new WalletAuthError(finalPayload.error_code, finalPayload.details);
|
|
1668
|
+
}
|
|
1669
|
+
return {
|
|
1670
|
+
address: finalPayload.address,
|
|
1671
|
+
message: finalPayload.message,
|
|
1672
|
+
signature: finalPayload.signature
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
// src/helpers/microphone.ts
|
|
1677
|
+
var microphoneSetupDone = false;
|
|
1678
|
+
var setupMicrophone = () => {
|
|
1679
|
+
if (microphoneSetupDone) {
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
if (typeof navigator !== "undefined" && !navigator.mediaDevices?.getUserMedia)
|
|
1683
|
+
return;
|
|
1684
|
+
const originalStop = MediaStreamTrack.prototype.stop;
|
|
1685
|
+
MediaStreamTrack.prototype.stop = function() {
|
|
1686
|
+
originalStop.call(this);
|
|
1687
|
+
if (this.readyState === "ended") {
|
|
1688
|
+
setTimeout(() => this.dispatchEvent(new Event("ended")), 0);
|
|
1689
|
+
}
|
|
1690
|
+
};
|
|
1691
|
+
const realGUM = navigator.mediaDevices.getUserMedia.bind(
|
|
1692
|
+
navigator.mediaDevices
|
|
1693
|
+
);
|
|
1694
|
+
const live = /* @__PURE__ */ new Set();
|
|
1695
|
+
async function wrapped(constraints) {
|
|
1696
|
+
const stream = await realGUM(constraints);
|
|
1697
|
+
const hasAudioTrack = stream.getAudioTracks().length > 0;
|
|
1698
|
+
if (hasAudioTrack) {
|
|
1699
|
+
sendMiniKitEvent({
|
|
1700
|
+
command: "microphone-stream-started",
|
|
1701
|
+
version: 1,
|
|
1702
|
+
payload: {
|
|
1703
|
+
streamId: stream.id
|
|
1704
|
+
}
|
|
1705
|
+
});
|
|
1706
|
+
live.add(stream);
|
|
1707
|
+
stream.getAudioTracks().forEach((t) => {
|
|
1708
|
+
t.addEventListener("ended", () => {
|
|
1709
|
+
const allAudioTracksEnded = stream.getAudioTracks().every((track) => track.readyState === "ended");
|
|
1710
|
+
if (allAudioTracksEnded) {
|
|
1711
|
+
sendMiniKitEvent({
|
|
1712
|
+
command: "microphone-stream-ended",
|
|
1713
|
+
version: 1,
|
|
1714
|
+
payload: {
|
|
1715
|
+
streamId: stream.id
|
|
1716
|
+
}
|
|
1717
|
+
});
|
|
1718
|
+
live.delete(stream);
|
|
1719
|
+
}
|
|
1720
|
+
});
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1723
|
+
return stream;
|
|
1724
|
+
}
|
|
1725
|
+
Object.defineProperty(navigator.mediaDevices, "getUserMedia", {
|
|
1726
|
+
value: wrapped,
|
|
1727
|
+
writable: false,
|
|
1728
|
+
configurable: false,
|
|
1729
|
+
enumerable: true
|
|
1730
|
+
});
|
|
1731
|
+
Object.freeze(navigator.mediaDevices);
|
|
1732
|
+
const stopAllMiniAppMicrophoneStreams = () => {
|
|
1733
|
+
live.forEach((s) => {
|
|
1734
|
+
const audioTracks = s.getAudioTracks();
|
|
1735
|
+
if (audioTracks.length > 0) {
|
|
1736
|
+
audioTracks.forEach((t) => {
|
|
1737
|
+
t.stop();
|
|
1738
|
+
});
|
|
1739
|
+
sendMiniKitEvent({
|
|
1740
|
+
command: "microphone-stream-ended",
|
|
1741
|
+
version: 1,
|
|
1742
|
+
payload: {
|
|
1743
|
+
streamId: s.id
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
});
|
|
1748
|
+
live.clear();
|
|
1749
|
+
};
|
|
1750
|
+
MiniKit.subscribe("miniapp-microphone" /* MiniAppMicrophone */, (payload) => {
|
|
1751
|
+
if (payload.status === "error" && (payload.error_code === "mini_app_permission_not_enabled" /* MiniAppPermissionNotEnabled */ || payload.error_code === "world_app_permission_not_enabled" /* WorldAppPermissionNotEnabled */)) {
|
|
1752
|
+
console.log("stopping all microphone streams", payload);
|
|
1753
|
+
stopAllMiniAppMicrophoneStreams();
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
window.__stopAllMiniAppMicrophoneStreams = stopAllMiniAppMicrophoneStreams;
|
|
1757
|
+
microphoneSetupDone = true;
|
|
1758
|
+
};
|
|
1759
|
+
|
|
1760
|
+
// src/helpers/usernames.ts
|
|
1761
|
+
var getUserProfile = async (address) => {
|
|
1762
|
+
const res = await fetch("https://usernames.worldcoin.org/api/v1/query", {
|
|
1763
|
+
method: "POST",
|
|
1764
|
+
headers: {
|
|
1765
|
+
"Content-Type": "application/json"
|
|
1766
|
+
},
|
|
1767
|
+
body: JSON.stringify({
|
|
1768
|
+
addresses: [address]
|
|
1769
|
+
})
|
|
1770
|
+
});
|
|
1771
|
+
const usernames = await res.json();
|
|
1772
|
+
return usernames?.[0] ?? { username: null, profile_picture_url: null };
|
|
1773
|
+
};
|
|
1774
|
+
|
|
1775
|
+
// src/types.ts
|
|
1776
|
+
var MiniKitInstallErrorMessage = {
|
|
1777
|
+
["unknown" /* Unknown */]: "Failed to install MiniKit.",
|
|
1778
|
+
["already_installed" /* AlreadyInstalled */]: "MiniKit is already installed.",
|
|
1779
|
+
["outside_of_worldapp" /* OutsideOfWorldApp */]: "MiniApp launched outside of WorldApp.",
|
|
1780
|
+
["not_on_client" /* NotOnClient */]: "Window object is not available.",
|
|
1781
|
+
["app_out_of_date" /* AppOutOfDate */]: "WorldApp is out of date. Please update the app."
|
|
1782
|
+
};
|
|
1783
|
+
|
|
1784
|
+
// src/minikit.ts
|
|
1785
|
+
var MINIKIT_VERSION = 1;
|
|
1786
|
+
var MINIKIT_MINOR_VERSION = 96;
|
|
1787
|
+
var WORLD_APP_LAUNCH_LOCATION_MAP = {
|
|
1788
|
+
"app-store": "app-store" /* AppStore */,
|
|
1789
|
+
carousel: "app-store" /* AppStore */,
|
|
1790
|
+
explore: "app-store" /* AppStore */,
|
|
1791
|
+
app_details: "app-store" /* AppStore */,
|
|
1792
|
+
deeplink: "deep-link" /* DeepLink */,
|
|
1793
|
+
homepage: "home" /* Home */,
|
|
1794
|
+
wallet_tab: "wallet-tab" /* WalletTab */,
|
|
1795
|
+
world_chat: "chat" /* Chat */
|
|
1796
|
+
};
|
|
1797
|
+
function mapWorldAppLaunchLocation(location) {
|
|
1798
|
+
if (!location || typeof location !== "string") return null;
|
|
1799
|
+
console.log("MiniKit launch location mapped:", location);
|
|
1800
|
+
return WORLD_APP_LAUNCH_LOCATION_MAP[location.toLowerCase()] ?? null;
|
|
1801
|
+
}
|
|
1802
|
+
var _MiniKit = class _MiniKit {
|
|
1803
|
+
static getActiveMiniKit() {
|
|
1804
|
+
if (typeof window === "undefined") return this;
|
|
1805
|
+
const candidate = window.MiniKit;
|
|
1806
|
+
if (candidate && typeof candidate.trigger === "function") {
|
|
1807
|
+
return candidate;
|
|
1808
|
+
}
|
|
1809
|
+
return this;
|
|
1810
|
+
}
|
|
1811
|
+
// ============================================================================
|
|
1812
|
+
// Unified API (auto-detects environment)
|
|
1813
|
+
// ============================================================================
|
|
1814
|
+
/**
|
|
1815
|
+
* Authenticate user via wallet signature (SIWE)
|
|
1816
|
+
*
|
|
1817
|
+
* Works in World App (native SIWE) and web (Wagmi + SIWE fallback).
|
|
1818
|
+
*
|
|
1819
|
+
* @example
|
|
1820
|
+
* ```typescript
|
|
1821
|
+
* const result = await MiniKit.walletAuth({ nonce: 'randomnonce123' });
|
|
1822
|
+
* console.log(result.data.address);
|
|
1823
|
+
* console.log(result.executedWith); // 'minikit' | 'wagmi' | 'fallback'
|
|
1824
|
+
* ```
|
|
1825
|
+
*/
|
|
1826
|
+
static walletAuth(options) {
|
|
1827
|
+
const active = this.getActiveMiniKit();
|
|
1828
|
+
if (active !== this) {
|
|
1829
|
+
return active.walletAuth(options);
|
|
1830
|
+
}
|
|
1831
|
+
return walletAuth(options, this.getContext());
|
|
1832
|
+
}
|
|
1833
|
+
/**
|
|
1834
|
+
* Send one or more transactions
|
|
1835
|
+
*
|
|
1836
|
+
* World App: batch + permit2 + gas sponsorship
|
|
1837
|
+
* Web: sequential execution via Wagmi
|
|
1838
|
+
*
|
|
1839
|
+
* @example
|
|
1840
|
+
* ```typescript
|
|
1841
|
+
* const result = await MiniKit.sendTransaction({
|
|
1842
|
+
* chainId: 480,
|
|
1843
|
+
* transactions: [{
|
|
1844
|
+
* to: '0x...',
|
|
1845
|
+
* data: '0x...',
|
|
1846
|
+
* value: '0x0',
|
|
1847
|
+
* }],
|
|
1848
|
+
* });
|
|
1849
|
+
* ```
|
|
1850
|
+
*/
|
|
1851
|
+
static sendTransaction(options) {
|
|
1852
|
+
const active = this.getActiveMiniKit();
|
|
1853
|
+
if (active !== this) {
|
|
1854
|
+
return active.sendTransaction(options);
|
|
1855
|
+
}
|
|
1856
|
+
return sendTransaction(options, this.getContext());
|
|
1857
|
+
}
|
|
1858
|
+
/**
|
|
1859
|
+
* Send a payment (World App only)
|
|
1860
|
+
*
|
|
1861
|
+
* Requires custom fallback on web.
|
|
1862
|
+
*
|
|
1863
|
+
* @example
|
|
1864
|
+
* ```typescript
|
|
1865
|
+
* const result = await MiniKit.pay({
|
|
1866
|
+
* reference: crypto.randomUUID(),
|
|
1867
|
+
* to: '0x...',
|
|
1868
|
+
* tokens: [{ symbol: Tokens.WLD, token_amount: '1.0' }],
|
|
1869
|
+
* description: 'Payment for coffee',
|
|
1870
|
+
* fallback: () => showStripeCheckout(),
|
|
1871
|
+
* });
|
|
1872
|
+
* ```
|
|
1873
|
+
*/
|
|
1874
|
+
static pay(options) {
|
|
1875
|
+
const active = this.getActiveMiniKit();
|
|
1876
|
+
if (active !== this) {
|
|
1877
|
+
return active.pay(options);
|
|
1878
|
+
}
|
|
1879
|
+
return pay(options, this.getContext());
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* Open the contact picker (World App only)
|
|
1883
|
+
*
|
|
1884
|
+
* Requires custom fallback on web.
|
|
1885
|
+
*
|
|
1886
|
+
* @example
|
|
1887
|
+
* ```typescript
|
|
1888
|
+
* const result = await MiniKit.shareContacts({
|
|
1889
|
+
* isMultiSelectEnabled: true,
|
|
1890
|
+
* fallback: () => showManualAddressInput(),
|
|
1891
|
+
* });
|
|
1892
|
+
* ```
|
|
1893
|
+
*/
|
|
1894
|
+
static shareContacts(options = {}) {
|
|
1895
|
+
const active = this.getActiveMiniKit();
|
|
1896
|
+
if (active !== this) {
|
|
1897
|
+
return active.shareContacts(options);
|
|
1898
|
+
}
|
|
1899
|
+
return shareContacts(options, this.getContext());
|
|
1900
|
+
}
|
|
1901
|
+
/**
|
|
1902
|
+
* Sign a message
|
|
1903
|
+
*/
|
|
1904
|
+
static signMessage(options) {
|
|
1905
|
+
const active = this.getActiveMiniKit();
|
|
1906
|
+
if (active !== this) {
|
|
1907
|
+
return active.signMessage(options);
|
|
1908
|
+
}
|
|
1909
|
+
return signMessage(options, this.getContext());
|
|
1910
|
+
}
|
|
1911
|
+
/**
|
|
1912
|
+
* Sign typed data (EIP-712)
|
|
1913
|
+
*/
|
|
1914
|
+
static signTypedData(options) {
|
|
1915
|
+
const active = this.getActiveMiniKit();
|
|
1916
|
+
if (active !== this) {
|
|
1917
|
+
return active.signTypedData(options);
|
|
1918
|
+
}
|
|
1919
|
+
return signTypedData(options, this.getContext());
|
|
1920
|
+
}
|
|
1921
|
+
/**
|
|
1922
|
+
* Send a chat message
|
|
1923
|
+
*/
|
|
1924
|
+
static chat(options) {
|
|
1925
|
+
const active = this.getActiveMiniKit();
|
|
1926
|
+
if (active !== this) {
|
|
1927
|
+
return active.chat(options);
|
|
1928
|
+
}
|
|
1929
|
+
return chat(options, this.getContext());
|
|
1930
|
+
}
|
|
1931
|
+
/**
|
|
1932
|
+
* Share files/text/URL
|
|
1933
|
+
*/
|
|
1934
|
+
static share(options) {
|
|
1935
|
+
const active = this.getActiveMiniKit();
|
|
1936
|
+
if (active !== this) {
|
|
1937
|
+
return active.share(options);
|
|
1938
|
+
}
|
|
1939
|
+
return share(options, this.getContext());
|
|
1940
|
+
}
|
|
1941
|
+
/**
|
|
1942
|
+
* Get current permission settings
|
|
1943
|
+
*/
|
|
1944
|
+
static getPermissions(options = {}) {
|
|
1945
|
+
const active = this.getActiveMiniKit();
|
|
1946
|
+
if (active !== this) {
|
|
1947
|
+
return active.getPermissions(options);
|
|
1948
|
+
}
|
|
1949
|
+
return getPermissions(options, this.getContext());
|
|
1950
|
+
}
|
|
1951
|
+
/**
|
|
1952
|
+
* Request a permission from the user
|
|
1953
|
+
*/
|
|
1954
|
+
static requestPermission(options) {
|
|
1955
|
+
const active = this.getActiveMiniKit();
|
|
1956
|
+
if (active !== this) {
|
|
1957
|
+
return active.requestPermission(options);
|
|
1958
|
+
}
|
|
1959
|
+
return requestPermission(options, this.getContext());
|
|
1960
|
+
}
|
|
1961
|
+
/**
|
|
1962
|
+
* Trigger haptic feedback
|
|
1963
|
+
*/
|
|
1964
|
+
static sendHapticFeedback(options) {
|
|
1965
|
+
const active = this.getActiveMiniKit();
|
|
1966
|
+
if (active !== this) {
|
|
1967
|
+
return active.sendHapticFeedback(options);
|
|
1968
|
+
}
|
|
1969
|
+
return sendHapticFeedback(options, this.getContext());
|
|
1970
|
+
}
|
|
1971
|
+
/**
|
|
1972
|
+
* Request app attestation token for a request hash
|
|
1973
|
+
*/
|
|
1974
|
+
static attestation(options) {
|
|
1975
|
+
const active = this.getActiveMiniKit();
|
|
1976
|
+
if (active !== this) {
|
|
1977
|
+
return active.attestation(options);
|
|
1978
|
+
}
|
|
1979
|
+
return attestation(options, this.getContext());
|
|
1980
|
+
}
|
|
1981
|
+
/**
|
|
1982
|
+
* Close the mini app
|
|
1983
|
+
*/
|
|
1984
|
+
static closeMiniApp(options = {}) {
|
|
1985
|
+
const active = this.getActiveMiniKit();
|
|
1986
|
+
if (active !== this) {
|
|
1987
|
+
return active.closeMiniApp(options);
|
|
1988
|
+
}
|
|
1989
|
+
return closeMiniApp(options, this.getContext());
|
|
1990
|
+
}
|
|
1991
|
+
// ============================================================================
|
|
1992
|
+
// Public State Accessors
|
|
1993
|
+
// ============================================================================
|
|
1994
|
+
static get appId() {
|
|
1995
|
+
return this._appId;
|
|
1996
|
+
}
|
|
1997
|
+
static set appId(value) {
|
|
1998
|
+
this._appId = value;
|
|
1999
|
+
}
|
|
2000
|
+
static get user() {
|
|
2001
|
+
return this._user;
|
|
2002
|
+
}
|
|
2003
|
+
static set user(value) {
|
|
2004
|
+
this._user = value;
|
|
2005
|
+
}
|
|
2006
|
+
static get deviceProperties() {
|
|
2007
|
+
return this._deviceProperties;
|
|
2008
|
+
}
|
|
2009
|
+
static get location() {
|
|
2010
|
+
return this._location;
|
|
2011
|
+
}
|
|
2012
|
+
// ============================================================================
|
|
2013
|
+
// Event System
|
|
2014
|
+
// ============================================================================
|
|
2015
|
+
static subscribe(event, handler) {
|
|
2016
|
+
const active = this.getActiveMiniKit();
|
|
2017
|
+
if (active !== this) {
|
|
2018
|
+
active.subscribe(event, handler);
|
|
2019
|
+
return;
|
|
2020
|
+
}
|
|
2021
|
+
if (event === "miniapp-wallet-auth" /* MiniAppWalletAuth */) {
|
|
2022
|
+
const originalHandler = handler;
|
|
2023
|
+
const wrappedHandler = async (payload) => {
|
|
2024
|
+
if (payload.status === "success") {
|
|
2025
|
+
await this.updateUserFromWalletAuth(payload.address);
|
|
2026
|
+
}
|
|
2027
|
+
originalHandler(payload);
|
|
2028
|
+
};
|
|
2029
|
+
this.eventManager.subscribe(event, wrappedHandler);
|
|
2030
|
+
} else {
|
|
2031
|
+
this.eventManager.subscribe(event, handler);
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
static unsubscribe(event) {
|
|
2035
|
+
const active = this.getActiveMiniKit();
|
|
2036
|
+
if (active !== this) {
|
|
2037
|
+
active.unsubscribe(event);
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
this.eventManager.unsubscribe(event);
|
|
2041
|
+
}
|
|
2042
|
+
static trigger(event, payload) {
|
|
2043
|
+
const active = this.getActiveMiniKit();
|
|
2044
|
+
if (active !== this) {
|
|
2045
|
+
active.trigger(event, payload);
|
|
2046
|
+
return;
|
|
2047
|
+
}
|
|
2048
|
+
this.eventManager.trigger(event, payload);
|
|
2049
|
+
}
|
|
2050
|
+
// ============================================================================
|
|
2051
|
+
// Installation
|
|
2052
|
+
// ============================================================================
|
|
2053
|
+
static sendInit() {
|
|
2054
|
+
sendMiniKitEvent({
|
|
2055
|
+
command: "init",
|
|
2056
|
+
payload: {
|
|
2057
|
+
version: MINIKIT_VERSION,
|
|
2058
|
+
minorVersion: MINIKIT_MINOR_VERSION
|
|
2059
|
+
}
|
|
2060
|
+
});
|
|
2061
|
+
}
|
|
2062
|
+
static install(appId) {
|
|
2063
|
+
const active = this.getActiveMiniKit();
|
|
2064
|
+
if (active !== this) {
|
|
2065
|
+
return active.install(appId);
|
|
2066
|
+
}
|
|
2067
|
+
if (typeof window === "undefined") {
|
|
2068
|
+
return {
|
|
2069
|
+
success: false,
|
|
2070
|
+
errorCode: "already_installed" /* AlreadyInstalled */,
|
|
2071
|
+
errorMessage: MiniKitInstallErrorMessage["already_installed" /* AlreadyInstalled */]
|
|
2072
|
+
};
|
|
2073
|
+
}
|
|
2074
|
+
if (!appId) {
|
|
2075
|
+
console.warn("App ID not provided during install");
|
|
2076
|
+
} else {
|
|
2077
|
+
this._appId = appId;
|
|
2078
|
+
}
|
|
2079
|
+
if (!window.WorldApp) {
|
|
2080
|
+
return {
|
|
2081
|
+
success: false,
|
|
2082
|
+
errorCode: "outside_of_worldapp" /* OutsideOfWorldApp */,
|
|
2083
|
+
errorMessage: MiniKitInstallErrorMessage["outside_of_worldapp" /* OutsideOfWorldApp */]
|
|
2084
|
+
};
|
|
2085
|
+
}
|
|
2086
|
+
this.initFromWorldApp(window.WorldApp);
|
|
2087
|
+
try {
|
|
2088
|
+
window.MiniKit = this;
|
|
2089
|
+
this.sendInit();
|
|
2090
|
+
} catch (error) {
|
|
2091
|
+
console.error(
|
|
2092
|
+
MiniKitInstallErrorMessage["unknown" /* Unknown */],
|
|
2093
|
+
error
|
|
2094
|
+
);
|
|
2095
|
+
return {
|
|
2096
|
+
success: false,
|
|
2097
|
+
errorCode: "unknown" /* Unknown */,
|
|
2098
|
+
errorMessage: MiniKitInstallErrorMessage["unknown" /* Unknown */]
|
|
2099
|
+
};
|
|
2100
|
+
}
|
|
2101
|
+
this._isReady = true;
|
|
2102
|
+
setupMicrophone();
|
|
2103
|
+
if (!validateCommands(window.WorldApp.supported_commands)) {
|
|
2104
|
+
return {
|
|
2105
|
+
success: false,
|
|
2106
|
+
errorCode: "app_out_of_date" /* AppOutOfDate */,
|
|
2107
|
+
errorMessage: MiniKitInstallErrorMessage["app_out_of_date" /* AppOutOfDate */]
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
return { success: true };
|
|
2111
|
+
}
|
|
2112
|
+
static isInstalled(debug) {
|
|
2113
|
+
const isInstalled = this._isReady && Boolean(window.MiniKit);
|
|
2114
|
+
if (!isInstalled) {
|
|
2115
|
+
console.warn(
|
|
2116
|
+
"MiniKit is not installed. Make sure you're running the application inside of World App"
|
|
2117
|
+
);
|
|
2118
|
+
}
|
|
2119
|
+
if (debug && isInstalled) {
|
|
2120
|
+
console.log("MiniKit is alive!");
|
|
2121
|
+
}
|
|
2122
|
+
return isInstalled;
|
|
2123
|
+
}
|
|
2124
|
+
// ============================================================================
|
|
2125
|
+
// Internal
|
|
2126
|
+
// ============================================================================
|
|
2127
|
+
static initFromWorldApp(worldApp2) {
|
|
2128
|
+
if (!worldApp2) return;
|
|
2129
|
+
this._user.optedIntoOptionalAnalytics = worldApp2.is_optional_analytics;
|
|
2130
|
+
this._deviceProperties.safeAreaInsets = worldApp2.safe_area_insets;
|
|
2131
|
+
this._deviceProperties.deviceOS = worldApp2.device_os;
|
|
2132
|
+
this._deviceProperties.worldAppVersion = worldApp2.world_app_version;
|
|
2133
|
+
this._location = mapWorldAppLaunchLocation(worldApp2.location);
|
|
2134
|
+
}
|
|
2135
|
+
static async updateUserFromWalletAuth(address) {
|
|
2136
|
+
this._user.walletAddress = address;
|
|
2137
|
+
try {
|
|
2138
|
+
const userProfile = await getUserProfile(address);
|
|
2139
|
+
this._user.username = userProfile.username;
|
|
2140
|
+
this._user.profilePictureUrl = userProfile.profile_picture_url;
|
|
2141
|
+
} catch (error) {
|
|
2142
|
+
console.error("Failed to fetch user profile:", error);
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
static getContext() {
|
|
2146
|
+
return {
|
|
2147
|
+
events: this.eventManager,
|
|
2148
|
+
state: { deviceProperties: this._deviceProperties }
|
|
2149
|
+
};
|
|
2150
|
+
}
|
|
2151
|
+
// ============================================================================
|
|
2152
|
+
// Deprecated — remove in next major
|
|
2153
|
+
// ============================================================================
|
|
2154
|
+
/**
|
|
2155
|
+
* @deprecated Use `MiniKit.pay()`, `MiniKit.walletAuth()`, etc. directly.
|
|
2156
|
+
*
|
|
2157
|
+
* Migration guide:
|
|
2158
|
+
* - `MiniKit.commands.pay(payload)` → `await MiniKit.pay(options)`
|
|
2159
|
+
* - `MiniKit.commands.walletAuth(payload)` → `await MiniKit.walletAuth(options)`
|
|
2160
|
+
* - `MiniKit.commands.sendTransaction(payload)` → `await MiniKit.sendTransaction(options)`
|
|
2161
|
+
* - `MiniKit.commands.signMessage(payload)` → `await MiniKit.signMessage(input)`
|
|
2162
|
+
* - `MiniKit.commands.signTypedData(payload)` → `await MiniKit.signTypedData(input)`
|
|
2163
|
+
* - `MiniKit.commands.shareContacts(payload)` → `await MiniKit.shareContacts(options)`
|
|
2164
|
+
* - `MiniKit.commands.chat(payload)` → `await MiniKit.chat(input)`
|
|
2165
|
+
* - `MiniKit.commands.share(payload)` → `await MiniKit.share(input)`
|
|
2166
|
+
* - `MiniKit.commands.getPermissions()` → `await MiniKit.getPermissions()`
|
|
2167
|
+
* - `MiniKit.commands.requestPermission(payload)` → `await MiniKit.requestPermission(input)`
|
|
2168
|
+
* - `MiniKit.commands.sendHapticFeedback(payload)` → `await MiniKit.sendHapticFeedback(input)`
|
|
2169
|
+
* - `MiniKit.commands.attestation(payload)` → `await MiniKit.attestation(options)`
|
|
2170
|
+
* - `MiniKit.commands.closeMiniApp()` → `await MiniKit.closeMiniApp()`
|
|
2171
|
+
*/
|
|
2172
|
+
static get commands() {
|
|
2173
|
+
throw new Error(
|
|
2174
|
+
"MiniKit.commands has been removed. Use MiniKit.pay(), MiniKit.walletAuth(), etc. directly."
|
|
2175
|
+
);
|
|
2176
|
+
}
|
|
2177
|
+
/**
|
|
2178
|
+
* @deprecated Use `MiniKit.pay()`, `MiniKit.walletAuth()`, etc. directly. All commands are now async by default.
|
|
2179
|
+
*
|
|
2180
|
+
* See `MiniKit.commands` deprecation notice for the full migration guide.
|
|
2181
|
+
*/
|
|
2182
|
+
static get commandsAsync() {
|
|
2183
|
+
throw new Error(
|
|
2184
|
+
"MiniKit.commandsAsync has been removed. Use MiniKit.pay(), MiniKit.walletAuth(), etc. directly."
|
|
2185
|
+
);
|
|
2186
|
+
}
|
|
2187
|
+
};
|
|
2188
|
+
_MiniKit.eventManager = new EventManager();
|
|
2189
|
+
// State (was MiniKitState)
|
|
2190
|
+
_MiniKit._appId = null;
|
|
2191
|
+
_MiniKit._user = {};
|
|
2192
|
+
_MiniKit._deviceProperties = {};
|
|
2193
|
+
_MiniKit._location = null;
|
|
2194
|
+
_MiniKit._isReady = false;
|
|
2195
|
+
/**
|
|
2196
|
+
* Check if running inside World App
|
|
2197
|
+
*/
|
|
2198
|
+
_MiniKit.isInWorldApp = isInWorldApp;
|
|
2199
|
+
// ============================================================================
|
|
2200
|
+
// Utility Methods
|
|
2201
|
+
// ============================================================================
|
|
2202
|
+
_MiniKit.getUserByAddress = async (address) => {
|
|
2203
|
+
const walletAddress = address ?? _MiniKit._user.walletAddress;
|
|
2204
|
+
const userProfile = await getUserProfile(walletAddress);
|
|
2205
|
+
return {
|
|
2206
|
+
walletAddress,
|
|
2207
|
+
username: userProfile.username,
|
|
2208
|
+
profilePictureUrl: userProfile.profile_picture_url
|
|
2209
|
+
};
|
|
2210
|
+
};
|
|
2211
|
+
_MiniKit.getUserByUsername = async (username) => {
|
|
2212
|
+
const res = await fetch(
|
|
2213
|
+
`https://usernames.worldcoin.org/api/v1/${username}`,
|
|
2214
|
+
{
|
|
2215
|
+
method: "GET",
|
|
2216
|
+
headers: {
|
|
2217
|
+
"Content-Type": "application/json"
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
);
|
|
2221
|
+
const user = await res.json();
|
|
2222
|
+
return {
|
|
2223
|
+
walletAddress: user.address,
|
|
2224
|
+
username: user.username,
|
|
2225
|
+
profilePictureUrl: user.profile_picture_url
|
|
2226
|
+
};
|
|
2227
|
+
};
|
|
2228
|
+
_MiniKit.getUserInfo = _MiniKit.getUserByAddress;
|
|
2229
|
+
_MiniKit.getMiniAppUrl = (appId, path) => {
|
|
2230
|
+
const baseUrl = new URL("https://world.org/mini-app");
|
|
2231
|
+
baseUrl.searchParams.append("app_id", appId);
|
|
2232
|
+
if (path) {
|
|
2233
|
+
const fullPath = path.startsWith("/") ? path : `/${path}`;
|
|
2234
|
+
baseUrl.searchParams.append("path", encodeURIComponent(fullPath));
|
|
2235
|
+
}
|
|
2236
|
+
return baseUrl.toString();
|
|
2237
|
+
};
|
|
2238
|
+
_MiniKit.showProfileCard = (username, walletAddress) => {
|
|
2239
|
+
if (!username && !walletAddress) {
|
|
2240
|
+
console.error(
|
|
2241
|
+
"Either username or walletAddress must be provided to show profile card"
|
|
2242
|
+
);
|
|
2243
|
+
return;
|
|
2244
|
+
}
|
|
2245
|
+
if (username) {
|
|
2246
|
+
window.open(
|
|
2247
|
+
`worldapp://profile?username=${encodeURIComponent(username)}`
|
|
2248
|
+
);
|
|
2249
|
+
} else {
|
|
2250
|
+
window.open(
|
|
2251
|
+
`worldapp://profile?address=${encodeURIComponent(walletAddress || "")}`
|
|
2252
|
+
);
|
|
2253
|
+
}
|
|
2254
|
+
};
|
|
2255
|
+
var MiniKit = _MiniKit;
|
|
2256
|
+
|
|
2257
|
+
// src/provider.ts
|
|
2258
|
+
var import_viem2 = require("viem");
|
|
2259
|
+
function _getAddress() {
|
|
2260
|
+
if (typeof window === "undefined") return void 0;
|
|
2261
|
+
return window.__worldapp_eip1193_address__;
|
|
2262
|
+
}
|
|
2263
|
+
function _setAddress(addr) {
|
|
2264
|
+
if (typeof window === "undefined") return;
|
|
2265
|
+
try {
|
|
2266
|
+
window.__worldapp_eip1193_address__ = (0, import_viem2.getAddress)(addr);
|
|
2267
|
+
} catch {
|
|
2268
|
+
window.__worldapp_eip1193_address__ = addr;
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
function _clearAddress() {
|
|
2272
|
+
if (typeof window === "undefined") return;
|
|
2273
|
+
window.__worldapp_eip1193_address__ = void 0;
|
|
2274
|
+
}
|
|
2275
|
+
function rpcError(code, message) {
|
|
2276
|
+
return Object.assign(new Error(message), { code });
|
|
2277
|
+
}
|
|
2278
|
+
function isHexString(value) {
|
|
2279
|
+
return /^0x[0-9a-fA-F]*$/.test(value);
|
|
2280
|
+
}
|
|
2281
|
+
function isAddressString(value) {
|
|
2282
|
+
return /^0x[0-9a-fA-F]{40}$/.test(value);
|
|
2283
|
+
}
|
|
2284
|
+
function decodeHexToUtf8(hex) {
|
|
2285
|
+
const raw = hex.slice(2);
|
|
2286
|
+
if (raw.length % 2 !== 0) {
|
|
2287
|
+
throw new Error("Invalid hex string length");
|
|
2288
|
+
}
|
|
2289
|
+
const bytes = new Uint8Array(raw.length / 2);
|
|
2290
|
+
for (let i = 0; i < raw.length; i += 2) {
|
|
2291
|
+
bytes[i / 2] = parseInt(raw.slice(i, i + 2), 16);
|
|
2292
|
+
}
|
|
2293
|
+
return new TextDecoder().decode(bytes);
|
|
2294
|
+
}
|
|
2295
|
+
function asArrayParams(params) {
|
|
2296
|
+
if (params === void 0) return [];
|
|
2297
|
+
return Array.isArray(params) ? params : [params];
|
|
2298
|
+
}
|
|
2299
|
+
function decodeMaybeHexMessage(value) {
|
|
2300
|
+
if (!isHexString(value)) {
|
|
2301
|
+
return value;
|
|
2302
|
+
}
|
|
2303
|
+
try {
|
|
2304
|
+
return decodeHexToUtf8(value);
|
|
2305
|
+
} catch {
|
|
2306
|
+
return value;
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
function extractPersonalSignMessage(params) {
|
|
2310
|
+
const items = asArrayParams(params);
|
|
2311
|
+
if (items.length === 0) {
|
|
2312
|
+
throw new Error("Missing personal_sign params");
|
|
2313
|
+
}
|
|
2314
|
+
const [first, second] = items;
|
|
2315
|
+
const maybeMessage = typeof first === "string" && isAddressString(first) && typeof second === "string" ? second : first;
|
|
2316
|
+
if (typeof maybeMessage !== "string") {
|
|
2317
|
+
throw new Error("Invalid personal_sign message payload");
|
|
2318
|
+
}
|
|
2319
|
+
return decodeMaybeHexMessage(maybeMessage);
|
|
2320
|
+
}
|
|
2321
|
+
function extractEthSignMessage(params) {
|
|
2322
|
+
const items = asArrayParams(params);
|
|
2323
|
+
if (items.length === 0) {
|
|
2324
|
+
throw new Error("Missing eth_sign params");
|
|
2325
|
+
}
|
|
2326
|
+
const [first, second] = items;
|
|
2327
|
+
const maybeMessage = typeof second === "string" ? second : typeof first === "string" && !isAddressString(first) ? first : void 0;
|
|
2328
|
+
if (typeof maybeMessage !== "string") {
|
|
2329
|
+
throw new Error("Invalid eth_sign message payload");
|
|
2330
|
+
}
|
|
2331
|
+
return decodeMaybeHexMessage(maybeMessage);
|
|
2332
|
+
}
|
|
2333
|
+
function parseTypedDataInput(params) {
|
|
2334
|
+
const items = asArrayParams(params);
|
|
2335
|
+
const candidate = items.length > 1 ? items[1] : items[0];
|
|
2336
|
+
if (!candidate) {
|
|
2337
|
+
throw new Error("Missing typed data payload");
|
|
2338
|
+
}
|
|
2339
|
+
const parsed = typeof candidate === "string" ? JSON.parse(candidate) : candidate;
|
|
2340
|
+
if (!parsed || typeof parsed !== "object" || typeof parsed.primaryType !== "string" || typeof parsed.message !== "object" || !parsed.message || typeof parsed.types !== "object" || !parsed.types) {
|
|
2341
|
+
throw new Error("Invalid typed data payload");
|
|
2342
|
+
}
|
|
2343
|
+
const domainValue = parsed.domain;
|
|
2344
|
+
const chainIdValue = domainValue?.chainId ?? parsed.chainId;
|
|
2345
|
+
const parsedChainId = typeof chainIdValue === "string" ? Number(chainIdValue) : typeof chainIdValue === "number" ? chainIdValue : void 0;
|
|
2346
|
+
return {
|
|
2347
|
+
types: parsed.types,
|
|
2348
|
+
primaryType: parsed.primaryType,
|
|
2349
|
+
domain: domainValue,
|
|
2350
|
+
message: parsed.message,
|
|
2351
|
+
...Number.isFinite(parsedChainId) ? { chainId: parsedChainId } : {}
|
|
2352
|
+
};
|
|
2353
|
+
}
|
|
2354
|
+
function normalizeRpcValue(value) {
|
|
2355
|
+
if (value === void 0 || value === null) return void 0;
|
|
2356
|
+
if (typeof value === "string") return value;
|
|
2357
|
+
if (typeof value === "bigint") return `0x${value.toString(16)}`;
|
|
2358
|
+
if (typeof value === "number") return `0x${value.toString(16)}`;
|
|
2359
|
+
return String(value);
|
|
2360
|
+
}
|
|
2361
|
+
function extractTransactionParams(params) {
|
|
2362
|
+
const items = asArrayParams(params);
|
|
2363
|
+
const tx = items[0] ?? {};
|
|
2364
|
+
if (typeof tx.to !== "string" || !isAddressString(tx.to)) {
|
|
2365
|
+
throw new Error('Invalid transaction "to" address');
|
|
2366
|
+
}
|
|
2367
|
+
const chainId = typeof tx.chainId === "string" ? Number(tx.chainId) : typeof tx.chainId === "number" ? tx.chainId : void 0;
|
|
2368
|
+
const normalizedValue = normalizeRpcValue(tx.value);
|
|
2369
|
+
return {
|
|
2370
|
+
to: tx.to,
|
|
2371
|
+
...typeof tx.data === "string" ? { data: tx.data } : {},
|
|
2372
|
+
...normalizedValue !== void 0 ? { value: normalizedValue } : {},
|
|
2373
|
+
...Number.isFinite(chainId) ? { chainId } : {}
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
function extractSwitchChainId(params) {
|
|
2377
|
+
const items = asArrayParams(params);
|
|
2378
|
+
const payload = items[0] ?? {};
|
|
2379
|
+
const rawChainId = payload.chainId;
|
|
2380
|
+
const chainId = typeof rawChainId === "string" ? Number(rawChainId) : typeof rawChainId === "number" ? rawChainId : NaN;
|
|
2381
|
+
if (!Number.isFinite(chainId)) {
|
|
2382
|
+
throw new Error("Invalid chainId for wallet_switchEthereumChain");
|
|
2383
|
+
}
|
|
2384
|
+
return chainId;
|
|
2385
|
+
}
|
|
2386
|
+
function createProvider() {
|
|
2387
|
+
const listeners = {};
|
|
2388
|
+
function emit(event, ...args) {
|
|
2389
|
+
listeners[event]?.forEach((fn) => fn(...args));
|
|
2390
|
+
}
|
|
2391
|
+
let authInFlight;
|
|
2392
|
+
async function doAuth() {
|
|
2393
|
+
if (!MiniKit.isInWorldApp() || !MiniKit.isInstalled()) {
|
|
2394
|
+
throw rpcError(
|
|
2395
|
+
4900,
|
|
2396
|
+
"World App provider only works inside World App and must be installed"
|
|
2397
|
+
);
|
|
2398
|
+
}
|
|
2399
|
+
try {
|
|
2400
|
+
const result = await MiniKit.walletAuth({
|
|
2401
|
+
nonce: crypto.randomUUID().replace(/-/g, ""),
|
|
2402
|
+
statement: "Sign in with World App"
|
|
2403
|
+
});
|
|
2404
|
+
_setAddress(result.data.address);
|
|
2405
|
+
const addr = _getAddress();
|
|
2406
|
+
emit("accountsChanged", [addr]);
|
|
2407
|
+
return [addr];
|
|
2408
|
+
} catch (e) {
|
|
2409
|
+
throw rpcError(4001, `World App wallet auth failed: ${e.message}`);
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
return {
|
|
2413
|
+
async request({ method, params }) {
|
|
2414
|
+
switch (method) {
|
|
2415
|
+
case "eth_requestAccounts": {
|
|
2416
|
+
const existing = _getAddress();
|
|
2417
|
+
if (existing) return [existing];
|
|
2418
|
+
if (!authInFlight) {
|
|
2419
|
+
authInFlight = doAuth().finally(() => {
|
|
2420
|
+
authInFlight = void 0;
|
|
2421
|
+
});
|
|
2422
|
+
}
|
|
2423
|
+
return authInFlight;
|
|
2424
|
+
}
|
|
2425
|
+
case "eth_accounts": {
|
|
2426
|
+
const addr = _getAddress();
|
|
2427
|
+
return addr ? [addr] : [];
|
|
2428
|
+
}
|
|
2429
|
+
case "eth_chainId":
|
|
2430
|
+
return "0x1e0";
|
|
2431
|
+
// 480 = World Chain
|
|
2432
|
+
case "personal_sign": {
|
|
2433
|
+
const message = extractPersonalSignMessage(params);
|
|
2434
|
+
try {
|
|
2435
|
+
const result = await MiniKit.signMessage({ message });
|
|
2436
|
+
return result.data.signature;
|
|
2437
|
+
} catch (e) {
|
|
2438
|
+
throw rpcError(4001, `Sign message failed: ${e.message}`);
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
case "eth_sign": {
|
|
2442
|
+
const message = extractEthSignMessage(params);
|
|
2443
|
+
try {
|
|
2444
|
+
const result = await MiniKit.signMessage({ message });
|
|
2445
|
+
return result.data.signature;
|
|
2446
|
+
} catch (e) {
|
|
2447
|
+
throw rpcError(4001, `Sign message failed: ${e.message}`);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
case "eth_signTypedData":
|
|
2451
|
+
case "eth_signTypedData_v3":
|
|
2452
|
+
case "eth_signTypedData_v4": {
|
|
2453
|
+
try {
|
|
2454
|
+
const typedData = parseTypedDataInput(params);
|
|
2455
|
+
const result = await MiniKit.signTypedData({
|
|
2456
|
+
types: typedData.types,
|
|
2457
|
+
primaryType: typedData.primaryType,
|
|
2458
|
+
domain: typedData.domain,
|
|
2459
|
+
message: typedData.message,
|
|
2460
|
+
chainId: typedData.chainId
|
|
2461
|
+
});
|
|
2462
|
+
if (result.data.status === "error") {
|
|
2463
|
+
throw rpcError(
|
|
2464
|
+
4001,
|
|
2465
|
+
`Sign typed data failed: ${result.data.error_code}`
|
|
2466
|
+
);
|
|
2467
|
+
}
|
|
2468
|
+
return result.data.signature;
|
|
2469
|
+
} catch (e) {
|
|
2470
|
+
throw rpcError(4001, `Sign typed data failed: ${e.message}`);
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
case "eth_sendTransaction": {
|
|
2474
|
+
const tx = extractTransactionParams(params);
|
|
2475
|
+
if (tx.chainId !== void 0 && tx.chainId !== 480) {
|
|
2476
|
+
throw rpcError(4902, "World App only supports World Chain (480)");
|
|
2477
|
+
}
|
|
2478
|
+
try {
|
|
2479
|
+
const result = await MiniKit.sendTransaction({
|
|
2480
|
+
chainId: tx.chainId ?? 480,
|
|
2481
|
+
transactions: [
|
|
2482
|
+
{
|
|
2483
|
+
to: tx.to,
|
|
2484
|
+
...tx.data && tx.data !== "0x" ? { data: tx.data } : {},
|
|
2485
|
+
value: tx.value
|
|
2486
|
+
}
|
|
2487
|
+
]
|
|
2488
|
+
});
|
|
2489
|
+
return result.data.userOpHash;
|
|
2490
|
+
} catch (e) {
|
|
2491
|
+
throw rpcError(4001, `Send transaction failed: ${e.message}`);
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
case "wallet_switchEthereumChain": {
|
|
2495
|
+
const chainId = extractSwitchChainId(params);
|
|
2496
|
+
if (chainId !== 480) {
|
|
2497
|
+
throw rpcError(4902, "World App only supports World Chain (480)");
|
|
2498
|
+
}
|
|
2499
|
+
return null;
|
|
2500
|
+
}
|
|
2501
|
+
case "wallet_addEthereumChain": {
|
|
2502
|
+
throw rpcError(4200, "World App only supports World Chain (480)");
|
|
2503
|
+
}
|
|
2504
|
+
default:
|
|
2505
|
+
throw rpcError(4200, `Unsupported method: ${method}`);
|
|
2506
|
+
}
|
|
2507
|
+
},
|
|
2508
|
+
on(event, fn) {
|
|
2509
|
+
(listeners[event] ?? (listeners[event] = /* @__PURE__ */ new Set())).add(fn);
|
|
2510
|
+
},
|
|
2511
|
+
removeListener(event, fn) {
|
|
2512
|
+
listeners[event]?.delete(fn);
|
|
2513
|
+
}
|
|
2514
|
+
};
|
|
2515
|
+
}
|
|
2516
|
+
function getWorldAppProvider() {
|
|
2517
|
+
if (typeof window === "undefined") {
|
|
2518
|
+
return createProvider();
|
|
2519
|
+
}
|
|
2520
|
+
if (!window.__worldapp_eip1193_provider__) {
|
|
2521
|
+
window.__worldapp_eip1193_provider__ = createProvider();
|
|
2522
|
+
}
|
|
2523
|
+
return window.__worldapp_eip1193_provider__;
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2526
|
+
// src/connector/connector.ts
|
|
2527
|
+
function worldApp(options = {}) {
|
|
2528
|
+
const name = options.name ?? "World App";
|
|
2529
|
+
return createConnectorFn(name);
|
|
2530
|
+
}
|
|
2531
|
+
function createConnectorFn(name) {
|
|
2532
|
+
return (config) => {
|
|
2533
|
+
setWagmiConfig(config);
|
|
2534
|
+
const provider = getWorldAppProvider();
|
|
2535
|
+
return {
|
|
2536
|
+
id: "worldApp",
|
|
2537
|
+
name,
|
|
2538
|
+
type: "worldApp",
|
|
2539
|
+
async setup() {
|
|
2540
|
+
const existing = MiniKit.user?.walletAddress;
|
|
2541
|
+
if (existing) {
|
|
2542
|
+
_setAddress(existing);
|
|
2543
|
+
}
|
|
2544
|
+
},
|
|
2545
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2546
|
+
async connect(_parameters) {
|
|
2547
|
+
const accounts = await provider.request({
|
|
2548
|
+
method: "eth_requestAccounts"
|
|
2549
|
+
});
|
|
2550
|
+
return {
|
|
2551
|
+
accounts,
|
|
2552
|
+
chainId: 480
|
|
2553
|
+
};
|
|
2554
|
+
},
|
|
2555
|
+
async disconnect() {
|
|
2556
|
+
_clearAddress();
|
|
2557
|
+
},
|
|
2558
|
+
async getAccounts() {
|
|
2559
|
+
const addr = _getAddress();
|
|
2560
|
+
if (addr) return [addr];
|
|
2561
|
+
if (!MiniKit.isInWorldApp()) return [];
|
|
2562
|
+
try {
|
|
2563
|
+
const accounts = await provider.request({
|
|
2564
|
+
method: "eth_requestAccounts"
|
|
2565
|
+
});
|
|
2566
|
+
if (Array.isArray(accounts) && accounts.length > 0 && typeof accounts[0] === "string") {
|
|
2567
|
+
_setAddress(accounts[0]);
|
|
2568
|
+
return [_getAddress()];
|
|
2569
|
+
}
|
|
2570
|
+
} catch {
|
|
2571
|
+
}
|
|
2572
|
+
return [];
|
|
2573
|
+
},
|
|
2574
|
+
async getChainId() {
|
|
2575
|
+
return 480;
|
|
2576
|
+
},
|
|
2577
|
+
async getProvider() {
|
|
2578
|
+
return provider;
|
|
2579
|
+
},
|
|
2580
|
+
async isAuthorized() {
|
|
2581
|
+
return MiniKit.isInWorldApp() && !!_getAddress();
|
|
2582
|
+
},
|
|
2583
|
+
async switchChain({ chainId }) {
|
|
2584
|
+
if (chainId !== 480) {
|
|
2585
|
+
throw new Error("World App only supports World Chain (chainId: 480)");
|
|
2586
|
+
}
|
|
2587
|
+
return config.chains.find((c) => c.id === 480) ?? config.chains[0];
|
|
2588
|
+
},
|
|
2589
|
+
onAccountsChanged(_accounts) {
|
|
2590
|
+
},
|
|
2591
|
+
onChainChanged(_chainId) {
|
|
2592
|
+
},
|
|
2593
|
+
onDisconnect() {
|
|
2594
|
+
}
|
|
2595
|
+
};
|
|
2596
|
+
};
|
|
2597
|
+
}
|
|
2598
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2599
|
+
0 && (module.exports = {
|
|
2600
|
+
worldApp
|
|
2601
|
+
});
|