@worldcoin/minikit-js
Version:
minikit-js is our SDK for building mini-apps.
1,569 lines (1,529 loc) • 65 kB
JavaScript
"use strict";
"use client";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/minikit-provider.tsx
var minikit_provider_exports = {};
__export(minikit_provider_exports, {
MiniKitProvider: () => MiniKitProvider,
useMiniKit: () => useMiniKit
});
module.exports = __toCommonJS(minikit_provider_exports);
var import_react = require("react");
// src/global-keys.ts
var WAGMI_INSTALL_HOOK_KEY = "__minikit_install_wagmi_fallback__";
// src/commands/types.ts
var COMMAND_VERSIONS = {
["attestation" /* Attestation */]: 1,
["pay" /* Pay */]: 1,
["wallet-auth" /* WalletAuth */]: 2,
["send-transaction" /* SendTransaction */]: 2,
["sign-message" /* SignMessage */]: 1,
["sign-typed-data" /* SignTypedData */]: 1,
["share-contacts" /* ShareContacts */]: 1,
["request-permission" /* RequestPermission */]: 1,
["get-permissions" /* GetPermissions */]: 1,
["send-haptic-feedback" /* SendHapticFeedback */]: 1,
["share" /* Share */]: 1,
["chat" /* Chat */]: 1,
["close-miniapp" /* CloseMiniApp */]: 1
};
var commandAvailability = {
["attestation" /* Attestation */]: false,
["pay" /* Pay */]: false,
["wallet-auth" /* WalletAuth */]: false,
["send-transaction" /* SendTransaction */]: false,
["sign-message" /* SignMessage */]: false,
["sign-typed-data" /* SignTypedData */]: false,
["share-contacts" /* ShareContacts */]: false,
["request-permission" /* RequestPermission */]: false,
["get-permissions" /* GetPermissions */]: false,
["send-haptic-feedback" /* SendHapticFeedback */]: false,
["share" /* Share */]: false,
["chat" /* Chat */]: false,
["close-miniapp" /* CloseMiniApp */]: false
};
function isCommandAvailable(command) {
return commandAvailability[command] ?? false;
}
function setCommandAvailable(command, available) {
commandAvailability[command] = available;
}
function validateCommands(worldAppSupportedCommands) {
let allCommandsValid = true;
Object.entries(COMMAND_VERSIONS).forEach(([commandName, version]) => {
const commandInput = worldAppSupportedCommands.find(
(cmd) => cmd.name === commandName
);
let isCommandValid = false;
if (!commandInput) {
console.warn(
`Command ${commandName} is not supported by the app. Try updating the app version`
);
} else {
if (commandInput.supported_versions.includes(version)) {
setCommandAvailable(commandName, true);
isCommandValid = true;
} else {
isCommandValid = true;
console.warn(
`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.`
);
setCommandAvailable(commandName, true);
}
}
if (!isCommandValid) {
allCommandsValid = false;
}
});
return allCommandsValid;
}
function sendMiniKitEvent(payload) {
if (window.webkit) {
window.webkit?.messageHandlers?.minikit?.postMessage?.(payload);
} else if (window.Android) {
window.Android?.postMessage?.(JSON.stringify(payload));
}
}
function isInWorldApp() {
return typeof window !== "undefined" && Boolean(window.WorldApp);
}
var FallbackRequiredError = class extends Error {
constructor(command) {
super(
`${command} requires a fallback function when running outside World App. Provide a fallback option: MiniKit.${command}({ ..., fallback: () => yourFallback() })`
);
this.name = "FallbackRequiredError";
}
};
var CommandUnavailableError = class extends Error {
constructor(command, reason) {
const messages = {
notInWorldApp: "Not running inside World App",
commandNotSupported: "Command not supported in this environment",
oldAppVersion: "World App version does not support this command"
};
super(`${command} is unavailable: ${messages[reason]}`);
this.name = "CommandUnavailableError";
this.reason = reason;
}
};
// src/events.ts
var EventManager = class {
constructor() {
this.listeners = {
["miniapp-attestation" /* MiniAppAttestation */]: () => {
},
["miniapp-payment" /* MiniAppPayment */]: () => {
},
["miniapp-wallet-auth" /* MiniAppWalletAuth */]: () => {
},
["miniapp-send-transaction" /* MiniAppSendTransaction */]: () => {
},
["miniapp-sign-message" /* MiniAppSignMessage */]: () => {
},
["miniapp-sign-typed-data" /* MiniAppSignTypedData */]: () => {
},
["miniapp-share-contacts" /* MiniAppShareContacts */]: () => {
},
["miniapp-request-permission" /* MiniAppRequestPermission */]: () => {
},
["miniapp-get-permissions" /* MiniAppGetPermissions */]: () => {
},
["miniapp-send-haptic-feedback" /* MiniAppSendHapticFeedback */]: () => {
},
["miniapp-share" /* MiniAppShare */]: () => {
},
["miniapp-microphone" /* MiniAppMicrophone */]: () => {
},
["miniapp-chat" /* MiniAppChat */]: () => {
}
};
}
subscribe(event, handler) {
this.listeners[event] = handler;
}
unsubscribe(event) {
delete this.listeners[event];
}
trigger(event, payload) {
if (!this.listeners[event]) {
console.error(
`No handler for event ${event}, payload: ${JSON.stringify(payload)}`
);
return;
}
this.listeners[event](payload);
}
};
// src/commands/fallback.ts
var PartialExecutionError = class extends Error {
constructor(message, submitted, cause) {
super(message);
this.name = "PartialExecutionError";
this.submitted = submitted;
this.cause = cause;
}
};
async function executeWithFallback(options) {
const {
command,
nativeExecutor,
wagmiFallback,
customFallback,
requiresFallback = false
} = options;
const inWorldApp = isInWorldApp();
const commandAvailable = isCommandAvailable(command);
let nativeError;
if (inWorldApp && commandAvailable) {
try {
const data = await nativeExecutor();
return { data, executedWith: "minikit" };
} catch (error) {
nativeError = error;
console.warn(`Native ${command} failed, attempting fallback:`, error);
}
}
if (!inWorldApp && wagmiFallback) {
try {
const data = await wagmiFallback();
return { data, executedWith: "wagmi" };
} catch (error) {
if (error instanceof PartialExecutionError || error instanceof Error && error.name === "PartialExecutionError") {
throw error;
}
console.warn(`Wagmi fallback for ${command} failed:`, error);
}
}
if (!inWorldApp && customFallback) {
const data = await customFallback();
return { data, executedWith: "fallback" };
}
if (nativeError) {
throw nativeError;
}
if (requiresFallback && !inWorldApp) {
throw new FallbackRequiredError(command);
}
throw new CommandUnavailableError(command, determineFallbackReason(command));
}
function determineFallbackReason(command) {
if (!isInWorldApp()) {
return "notInWorldApp";
}
if (!isCommandAvailable(command)) {
return "oldAppVersion";
}
return "commandNotSupported";
}
// src/commands/attestation/types.ts
var AttestationError = class extends Error {
constructor(error_code) {
super(`Attestation failed: ${error_code}`);
this.error_code = error_code;
this.name = "AttestationError";
}
};
// src/commands/attestation/index.ts
async function attestation(options, ctx) {
const result = await executeWithFallback({
command: "attestation" /* Attestation */,
nativeExecutor: () => nativeAttestation(options, ctx),
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeAttestation(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("attestation" /* Attestation */)) {
throw new Error(
"'attestation' command is unavailable. Check MiniKit.install() or update the app version"
);
}
if (!options.requestHash || options.requestHash.length === 0) {
throw new Error("'attestation' command requires a non-empty requestHash");
}
const payload = await new Promise(
(resolve, reject) => {
try {
ctx.events.subscribe("miniapp-attestation" /* MiniAppAttestation */, (response) => {
ctx.events.unsubscribe("miniapp-attestation" /* MiniAppAttestation */);
resolve(response);
});
sendMiniKitEvent({
command: "attestation" /* Attestation */,
version: COMMAND_VERSIONS["attestation" /* Attestation */],
payload: {
request_hash: options.requestHash
}
});
} catch (error) {
reject(error);
}
}
);
if (payload.status === "error") {
throw new AttestationError(payload.error_code);
}
return payload;
}
// src/commands/chat/types.ts
var ChatError = class extends Error {
constructor(error_code) {
super(`Chat failed: ${error_code}`);
this.error_code = error_code;
this.name = "ChatError";
}
};
// src/commands/chat/index.ts
async function chat(options, ctx) {
const result = await executeWithFallback({
command: "chat" /* Chat */,
nativeExecutor: () => nativeChat(options, ctx),
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeChat(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("chat" /* Chat */)) {
throw new Error(
"'chat' command is unavailable. Check MiniKit.install() or update the app version"
);
}
const payloadInput = {
message: options.message,
to: options.to
};
if (payloadInput.message.length === 0) {
throw new Error("'chat' command requires a non-empty message");
}
const payload = await new Promise((resolve, reject) => {
try {
ctx.events.subscribe("miniapp-chat" /* MiniAppChat */, (response) => {
ctx.events.unsubscribe("miniapp-chat" /* MiniAppChat */);
resolve(response);
});
sendMiniKitEvent({
command: "chat" /* Chat */,
version: COMMAND_VERSIONS["chat" /* Chat */],
payload: payloadInput
});
} catch (error) {
reject(error);
}
});
if (payload.status === "error") {
throw new ChatError(payload.error_code);
}
return payload;
}
// src/commands/close-miniapp/index.ts
async function closeMiniApp(options = {}, _ctx) {
const result = await executeWithFallback({
command: "close-miniapp" /* CloseMiniApp */,
nativeExecutor: () => nativeCloseMiniApp(),
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeCloseMiniApp() {
if (typeof window === "undefined" || !isCommandAvailable("close-miniapp" /* CloseMiniApp */)) {
throw new Error(
"'closeMiniApp' command is unavailable. Check MiniKit.install() or update the app version"
);
}
sendMiniKitEvent({
command: "close-miniapp" /* CloseMiniApp */,
version: COMMAND_VERSIONS["close-miniapp" /* CloseMiniApp */],
payload: {}
});
return {
status: "success",
version: COMMAND_VERSIONS["close-miniapp" /* CloseMiniApp */]
};
}
// src/commands/get-permissions/types.ts
var GetPermissionsError = class extends Error {
constructor(error_code) {
super(`Get permissions failed: ${error_code}`);
this.error_code = error_code;
this.name = "GetPermissionsError";
}
};
// src/commands/get-permissions/index.ts
async function getPermissions(options, ctx) {
const resolvedOptions = options ?? {};
const result = await executeWithFallback({
command: "get-permissions" /* GetPermissions */,
nativeExecutor: () => nativeGetPermissions(ctx),
customFallback: resolvedOptions.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeGetPermissions(ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("get-permissions" /* GetPermissions */)) {
throw new Error(
"'getPermissions' command is unavailable. Check MiniKit.install() or update the app version"
);
}
const payload = await new Promise(
(resolve, reject) => {
try {
ctx.events.subscribe("miniapp-get-permissions" /* MiniAppGetPermissions */, (response) => {
ctx.events.unsubscribe("miniapp-get-permissions" /* MiniAppGetPermissions */);
resolve(response);
});
sendMiniKitEvent({
command: "get-permissions" /* GetPermissions */,
version: COMMAND_VERSIONS["get-permissions" /* GetPermissions */],
payload: {}
});
} catch (error) {
reject(error);
}
}
);
if (payload.status === "error") {
throw new GetPermissionsError(payload.error_code);
}
return payload;
}
// src/commands/pay/types.ts
var PayError = class extends Error {
constructor(code) {
super(`Payment failed: ${code}`);
this.name = "PayError";
this.code = code;
}
};
// src/commands/pay/validate.ts
var validatePaymentPayload = (payload) => {
if (payload.tokens.some(
(token) => token.symbol == "USDCE" /* USDC */ && parseFloat(token.token_amount) < 0.1
)) {
console.error("USDC amount should be greater than $0.1");
return false;
}
if (payload.reference.length > 36) {
console.error("Reference must not exceed 36 characters");
return false;
}
if (typeof payload.reference !== "string") {
throw new Error("Reference must be a string");
}
return true;
};
// src/commands/pay/index.ts
async function pay(options, ctx) {
const result = await executeWithFallback({
command: "pay" /* Pay */,
nativeExecutor: () => nativePay(options, ctx),
// No Wagmi fallback - pay is native only
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
return { executedWith: "minikit", data: result.data };
}
async function nativePay(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("pay" /* Pay */)) {
throw new Error(
"'pay' command is unavailable. Check MiniKit.install() or update the app version"
);
}
const input = {
reference: options.reference,
to: options.to,
tokens: options.tokens,
description: options.description,
network: options.network
};
if (!validatePaymentPayload(input)) {
throw new Error("Invalid payment payload");
}
const eventPayload = {
...input,
network: "worldchain" /* WorldChain */
};
const finalPayload = await new Promise(
(resolve, reject) => {
try {
ctx.events.subscribe("miniapp-payment" /* MiniAppPayment */, (response) => {
ctx.events.unsubscribe("miniapp-payment" /* MiniAppPayment */);
resolve(response);
});
sendMiniKitEvent({
command: "pay" /* Pay */,
version: COMMAND_VERSIONS["pay" /* Pay */],
payload: eventPayload
});
} catch (error) {
reject(error);
}
}
);
if (finalPayload.status === "error") {
throw new PayError(finalPayload.error_code);
}
return {
transactionId: finalPayload.transaction_id,
reference: finalPayload.reference,
from: finalPayload.from,
chain: finalPayload.chain,
timestamp: finalPayload.timestamp
};
}
// src/commands/request-permission/types.ts
var RequestPermissionError = class extends Error {
constructor(error_code) {
super(`Request permission failed: ${error_code}`);
this.error_code = error_code;
this.name = "RequestPermissionError";
}
};
// src/commands/request-permission/index.ts
async function requestPermission(options, ctx) {
const result = await executeWithFallback({
command: "request-permission" /* RequestPermission */,
nativeExecutor: () => nativeRequestPermission(options, ctx),
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeRequestPermission(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("request-permission" /* RequestPermission */)) {
throw new Error(
"'requestPermission' command is unavailable. Check MiniKit.install() or update the app version"
);
}
const payload = await new Promise(
(resolve, reject) => {
try {
ctx.events.subscribe("miniapp-request-permission" /* MiniAppRequestPermission */, (response) => {
ctx.events.unsubscribe("miniapp-request-permission" /* MiniAppRequestPermission */);
resolve(response);
});
sendMiniKitEvent({
command: "request-permission" /* RequestPermission */,
version: COMMAND_VERSIONS["request-permission" /* RequestPermission */],
payload: { permission: options.permission }
});
} catch (error) {
reject(error);
}
}
);
if (payload.status === "error") {
throw new RequestPermissionError(payload.error_code);
}
return payload;
}
// src/commands/send-haptic-feedback/types.ts
var SendHapticFeedbackError = class extends Error {
constructor(error_code) {
super(`Send haptic feedback failed: ${error_code}`);
this.error_code = error_code;
this.name = "SendHapticFeedbackError";
}
};
// src/commands/send-haptic-feedback/index.ts
async function sendHapticFeedback(options, ctx) {
const result = await executeWithFallback({
command: "send-haptic-feedback" /* SendHapticFeedback */,
nativeExecutor: () => nativeSendHapticFeedback(options, ctx),
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeSendHapticFeedback(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("send-haptic-feedback" /* SendHapticFeedback */)) {
throw new Error(
"'sendHapticFeedback' command is unavailable. Check MiniKit.install() or update the app version"
);
}
const payloadInput = options.hapticsType === "selection-changed" ? { hapticsType: "selection-changed" } : options.hapticsType === "impact" ? {
hapticsType: "impact",
style: options.style
} : {
hapticsType: "notification",
style: options.style
};
const payload = await new Promise(
(resolve, reject) => {
try {
ctx.events.subscribe("miniapp-send-haptic-feedback" /* MiniAppSendHapticFeedback */, (response) => {
ctx.events.unsubscribe("miniapp-send-haptic-feedback" /* MiniAppSendHapticFeedback */);
resolve(response);
});
sendMiniKitEvent({
command: "send-haptic-feedback" /* SendHapticFeedback */,
version: COMMAND_VERSIONS["send-haptic-feedback" /* SendHapticFeedback */],
payload: payloadInput
});
} catch (error) {
reject(error);
}
}
);
if (payload.status === "error") {
throw new SendHapticFeedbackError(payload.error_code);
}
return payload;
}
// src/commands/fallback-adapter-registry.ts
var FALLBACK_ADAPTER_KEY = "__minikit_fallback_adapter__";
function getFallbackAdapter() {
return globalThis[FALLBACK_ADAPTER_KEY];
}
// src/commands/send-transaction/types.ts
var SendTransactionError = class extends Error {
constructor(code, details) {
super(`Transaction failed: ${code}`);
this.name = "SendTransactionError";
this.code = code;
this.details = details;
}
};
// src/commands/send-transaction/validate.ts
var isValidHex = (str) => {
return /^0x[0-9A-Fa-f]+$/.test(str);
};
var processPayload = (payload) => {
if (typeof payload === "boolean" || typeof payload === "string" || payload === null || payload === void 0) {
return payload;
}
if (typeof payload === "number" || typeof payload === "bigint") {
return String(payload);
}
if (Array.isArray(payload)) {
return payload.map((value) => processPayload(value));
}
if (typeof payload === "object") {
const result = { ...payload };
if ("chainId" in result && result.chainId !== void 0) {
if (typeof result.chainId === "string") {
const parsed = Number(result.chainId);
if (Number.isFinite(parsed)) {
result.chainId = parsed;
}
} else if (typeof result.chainId === "bigint") {
const parsed = Number(result.chainId);
if (!Number.isSafeInteger(parsed)) {
throw new Error(`Invalid chainId: ${String(result.chainId)}`);
}
result.chainId = parsed;
}
}
if ("value" in result && result.value !== void 0) {
if (typeof result.value !== "string") {
result.value = String(result.value);
}
if (!isValidHex(result.value)) {
console.error(
"Transaction value must be a valid hex string",
result.value
);
throw new Error(
`Transaction value must be a valid hex string: ${result.value}`
);
}
}
for (const key in result) {
if (Object.prototype.hasOwnProperty.call(result, key)) {
if (key === "chainId") continue;
result[key] = processPayload(result[key]);
}
}
return result;
}
return payload;
};
var validateSendTransactionPayload = (payload) => {
return processPayload(payload);
};
// src/commands/send-transaction/index.ts
var WORLD_CHAIN_ID = 480;
function resolveChainId(options) {
return options.chainId;
}
function resolveTransactions(options) {
if (options.transactions.length === 0) {
throw new SendTransactionError("input_error" /* InputError */, {
reason: "At least one transaction is required. Use `transactions: [{ to, data, value }]`."
});
}
return options.transactions;
}
function normalizeSendTransactionOptions(options) {
const chainId = resolveChainId(options);
if (chainId !== WORLD_CHAIN_ID) {
throw new SendTransactionError("invalid_operation" /* InvalidOperation */, {
reason: `World App only supports World Chain (chainId: ${WORLD_CHAIN_ID})`
});
}
return {
transactions: resolveTransactions(options),
chainId
};
}
async function sendTransaction(options, ctx) {
const normalizedOptions = normalizeSendTransactionOptions(options);
const fallbackAdapter = getFallbackAdapter();
const result = await executeWithFallback({
command: "send-transaction" /* SendTransaction */,
nativeExecutor: () => nativeSendTransaction(normalizedOptions, ctx),
wagmiFallback: fallbackAdapter?.sendTransaction ? () => adapterSendTransactionFallback(normalizedOptions) : void 0,
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
if (result.executedWith === "wagmi") {
return {
executedWith: "wagmi",
data: result.data
};
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeSendTransaction(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("send-transaction" /* SendTransaction */)) {
throw new Error(
"'sendTransaction' command is unavailable. Check MiniKit.install() or update the app version"
);
}
if (options.chainId !== WORLD_CHAIN_ID) {
throw new Error(
`World App only supports World Chain (chainId: ${WORLD_CHAIN_ID})`
);
}
const commandInput = window.WorldApp?.supported_commands.find(
(command) => command.name === "send-transaction" /* SendTransaction */
);
if (commandInput && !commandInput.supported_versions.includes(
COMMAND_VERSIONS["send-transaction" /* SendTransaction */]
)) {
throw new CommandUnavailableError("send-transaction" /* SendTransaction */, "oldAppVersion");
}
const input = {
transactions: options.transactions,
chainId: options.chainId
};
const validatedPayload = validateSendTransactionPayload(input);
const finalPayload = await new Promise(
(resolve, reject) => {
try {
ctx.events.subscribe("miniapp-send-transaction" /* MiniAppSendTransaction */, (response) => {
ctx.events.unsubscribe("miniapp-send-transaction" /* MiniAppSendTransaction */);
resolve(response);
});
sendMiniKitEvent({
command: "send-transaction" /* SendTransaction */,
version: COMMAND_VERSIONS["send-transaction" /* SendTransaction */],
payload: validatedPayload
});
} catch (error) {
reject(error);
}
}
);
if (finalPayload.status === "error") {
throw new SendTransactionError(
finalPayload.error_code,
finalPayload.details
);
}
const successPayload = finalPayload;
return {
userOpHash: String(successPayload.userOpHash ?? ""),
status: finalPayload.status,
version: finalPayload.version,
from: String(successPayload.from ?? ""),
timestamp: String(successPayload.timestamp ?? (/* @__PURE__ */ new Date()).toISOString())
};
}
async function adapterSendTransactionFallback(options) {
const fallbackAdapter = getFallbackAdapter();
if (!fallbackAdapter?.sendTransaction) {
throw new Error("Fallback adapter is not registered.");
}
const result = await fallbackAdapter.sendTransaction({
transactions: options.transactions.map((tx) => ({
address: tx.to,
data: tx.data,
value: tx.value
})),
chainId: options.chainId
});
return {
userOpHash: result.transactionHash,
status: "success",
version: COMMAND_VERSIONS["send-transaction" /* SendTransaction */],
from: "",
timestamp: (/* @__PURE__ */ new Date()).toISOString()
};
}
// src/commands/share/format.ts
var MAX_FILES = 10;
var MAX_TOTAL_SIZE_MB = 50;
var MAX_TOTAL_SIZE_BYTES = MAX_TOTAL_SIZE_MB * 1024 * 1024;
var processFile = async (file) => {
const buffer = await file.arrayBuffer();
const uint8Array = new Uint8Array(buffer);
let binaryString = "";
const K_CHUNK_SIZE = 32768;
for (let i = 0; i < uint8Array.length; i += K_CHUNK_SIZE) {
const chunk = uint8Array.subarray(
i,
Math.min(i + K_CHUNK_SIZE, uint8Array.length)
);
binaryString += String.fromCharCode.apply(
null,
Array.from(chunk)
// Convert Uint8Array chunk to number[]
);
}
const base64Data = btoa(binaryString);
return {
name: file.name,
type: file.type,
data: base64Data
};
};
var formatShareInput = async (input) => {
if (!input.files) {
return {
title: input.title,
text: input.text,
url: input.url
};
}
if (!Array.isArray(input.files)) {
throw new Error('The "files" property must be an array.');
}
if (input.files.length === 0) {
} else {
if (input.files.length > MAX_FILES) {
throw new Error(`Cannot share more than ${MAX_FILES} files.`);
}
let totalSize = 0;
for (const file of input.files) {
if (!(file instanceof File)) {
throw new Error(
`Each item in the 'files' array must be a File object. Received: ${typeof file}`
);
}
totalSize += file.size;
}
if (totalSize > MAX_TOTAL_SIZE_BYTES) {
throw new Error(`Total file size cannot exceed ${MAX_TOTAL_SIZE_MB}MB.`);
}
}
const fileProcessingPromises = input.files.map((file) => processFile(file));
const processedFiles = await Promise.all(fileProcessingPromises);
return {
files: processedFiles,
title: input.title,
text: input.text,
url: input.url
};
};
// src/commands/share/types.ts
var ShareError = class extends Error {
constructor(error_code) {
super(`Share failed: ${error_code}`);
this.error_code = error_code;
this.name = "ShareError";
}
};
// src/commands/share/index.ts
async function share(options, ctx) {
const result = await executeWithFallback({
command: "share" /* Share */,
nativeExecutor: () => nativeShare(options, ctx),
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return {
executedWith: "fallback",
data: result.data
};
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeShare(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("share" /* Share */)) {
throw new Error(
"'share' command is unavailable. Check MiniKit.install() or update the app version"
);
}
const payloadInput = {
files: options.files,
title: options.title,
text: options.text,
url: options.url
};
if (ctx.state.deviceProperties.deviceOS === "ios" && typeof navigator !== "undefined") {
sendMiniKitEvent({
command: "share" /* Share */,
version: COMMAND_VERSIONS["share" /* Share */],
payload: payloadInput
});
await navigator.share(payloadInput);
return {
status: "success",
version: COMMAND_VERSIONS["share" /* Share */],
shared_files_count: payloadInput.files?.length ?? 0,
timestamp: (/* @__PURE__ */ new Date()).toISOString()
};
}
const formattedPayload = await formatShareInput(payloadInput);
const payload = await new Promise((resolve, reject) => {
try {
ctx.events.subscribe("miniapp-share" /* MiniAppShare */, (response) => {
ctx.events.unsubscribe("miniapp-share" /* MiniAppShare */);
resolve(response);
});
sendMiniKitEvent({
command: "share" /* Share */,
version: COMMAND_VERSIONS["share" /* Share */],
payload: formattedPayload
});
} catch (error) {
reject(error);
}
});
if (payload.status === "error") {
throw new ShareError(payload.error_code);
}
return payload;
}
// src/commands/share-contacts/types.ts
var ShareContactsError = class extends Error {
constructor(code) {
super(`Share contacts failed: ${code}`);
this.name = "ShareContactsError";
this.code = code;
}
};
// src/commands/share-contacts/index.ts
async function shareContacts(options, ctx) {
const resolvedOptions = options ?? {};
const result = await executeWithFallback({
command: "share-contacts" /* ShareContacts */,
nativeExecutor: () => nativeShareContacts(resolvedOptions, ctx),
// No Wagmi fallback - contacts is native only
customFallback: resolvedOptions.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
return { executedWith: "minikit", data: result.data };
}
async function nativeShareContacts(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("share-contacts" /* ShareContacts */)) {
throw new Error(
"'shareContacts' command is unavailable. Check MiniKit.install() or update the app version"
);
}
const payload = {
isMultiSelectEnabled: options.isMultiSelectEnabled ?? false,
inviteMessage: options.inviteMessage
};
const finalPayload = await new Promise(
(resolve, reject) => {
try {
ctx.events.subscribe("miniapp-share-contacts" /* MiniAppShareContacts */, (response) => {
ctx.events.unsubscribe("miniapp-share-contacts" /* MiniAppShareContacts */);
resolve(response);
});
sendMiniKitEvent({
command: "share-contacts" /* ShareContacts */,
version: COMMAND_VERSIONS["share-contacts" /* ShareContacts */],
payload
});
} catch (error) {
reject(error);
}
}
);
if (finalPayload.status === "error") {
throw new ShareContactsError(finalPayload.error_code);
}
return {
contacts: finalPayload.contacts,
timestamp: finalPayload.timestamp
};
}
// src/commands/sign-message/types.ts
var SignMessageError = class extends Error {
constructor(error_code) {
super(`Sign message failed: ${error_code}`);
this.error_code = error_code;
this.name = "SignMessageError";
}
};
// src/commands/sign-message/index.ts
async function signMessage(options, ctx) {
const fallbackAdapter = getFallbackAdapter();
const result = await executeWithFallback({
command: "sign-message" /* SignMessage */,
nativeExecutor: () => nativeSignMessage(options, ctx),
wagmiFallback: fallbackAdapter?.signMessage ? () => fallbackAdapter.signMessage({
message: options.message
}) : void 0,
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
if (result.executedWith === "wagmi") {
return {
executedWith: "wagmi",
data: result.data
};
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeSignMessage(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("sign-message" /* SignMessage */)) {
throw new Error(
"'signMessage' command is unavailable. Check MiniKit.install() or update the app version"
);
}
const payload = await new Promise(
(resolve, reject) => {
try {
ctx.events.subscribe("miniapp-sign-message" /* MiniAppSignMessage */, (response) => {
ctx.events.unsubscribe("miniapp-sign-message" /* MiniAppSignMessage */);
resolve(response);
});
sendMiniKitEvent({
command: "sign-message" /* SignMessage */,
version: COMMAND_VERSIONS["sign-message" /* SignMessage */],
payload: { message: options.message }
});
} catch (error) {
reject(error);
}
}
);
if (payload.status === "error") {
throw new SignMessageError(payload.error_code);
}
return payload;
}
// src/commands/sign-typed-data/types.ts
var SignTypedDataError = class extends Error {
constructor(error_code) {
super(`Sign typed data failed: ${error_code}`);
this.error_code = error_code;
this.name = "SignTypedDataError";
}
};
// src/commands/sign-typed-data/index.ts
async function signTypedData(options, ctx) {
const fallbackAdapter = getFallbackAdapter();
const result = await executeWithFallback({
command: "sign-typed-data" /* SignTypedData */,
nativeExecutor: () => nativeSignTypedData(options, ctx),
wagmiFallback: fallbackAdapter?.signTypedData ? () => fallbackAdapter.signTypedData({
types: options.types,
primaryType: options.primaryType,
message: options.message,
domain: options.domain,
chainId: options.chainId
}) : void 0,
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
if (result.executedWith === "wagmi") {
return {
executedWith: "wagmi",
data: result.data
};
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeSignTypedData(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("sign-typed-data" /* SignTypedData */)) {
throw new Error(
"'signTypedData' command is unavailable. Check MiniKit.install() or update the app version"
);
}
const payloadInput = {
types: options.types,
primaryType: options.primaryType,
message: options.message,
domain: options.domain,
chainId: options.chainId ?? 480
};
const payload = await new Promise(
(resolve, reject) => {
try {
ctx.events.subscribe("miniapp-sign-typed-data" /* MiniAppSignTypedData */, (response) => {
ctx.events.unsubscribe("miniapp-sign-typed-data" /* MiniAppSignTypedData */);
resolve(response);
});
sendMiniKitEvent({
command: "sign-typed-data" /* SignTypedData */,
version: COMMAND_VERSIONS["sign-typed-data" /* SignTypedData */],
payload: payloadInput
});
} catch (error) {
reject(error);
}
}
);
if (payload.status === "error") {
throw new SignTypedDataError(payload.error_code);
}
return payload;
}
// src/commands/wallet-auth/siwe.ts
var import_viem = require("viem");
var import_chains = require("viem/chains");
var generateSiweMessage = (siweMessageData) => {
let siweMessage = "";
if (siweMessageData.scheme) {
siweMessage += `${siweMessageData.scheme}://${siweMessageData.domain} wants you to sign in with your Ethereum account:
`;
} else {
siweMessage += `${siweMessageData.domain} wants you to sign in with your Ethereum account:
`;
}
if (siweMessageData.address) {
siweMessage += `${siweMessageData.address}
`;
} else {
siweMessage += "{address}\n";
}
siweMessage += "\n";
if (siweMessageData.statement) {
siweMessage += `${siweMessageData.statement}
`;
}
siweMessage += "\n";
siweMessage += `URI: ${siweMessageData.uri}
`;
siweMessage += `Version: ${siweMessageData.version}
`;
siweMessage += `Chain ID: ${siweMessageData.chain_id}
`;
siweMessage += `Nonce: ${siweMessageData.nonce}
`;
siweMessage += `Issued At: ${siweMessageData.issued_at}
`;
if (siweMessageData.expiration_time) {
siweMessage += `Expiration Time: ${siweMessageData.expiration_time}
`;
}
if (siweMessageData.not_before) {
siweMessage += `Not Before: ${siweMessageData.not_before}
`;
}
if (siweMessageData.request_id) {
siweMessage += `Request ID: ${siweMessageData.request_id}
`;
}
return siweMessage;
};
// src/commands/wallet-auth/types.ts
var WalletAuthError = class extends Error {
constructor(code, details) {
super(details || `Wallet auth failed: ${code}`);
this.name = "WalletAuthError";
this.code = code;
this.details = details;
}
};
// src/commands/wallet-auth/validate.ts
var SIWE_NONCE_REGEX = /^[a-zA-Z0-9]+$/;
var validateWalletAuthCommandInput = (params) => {
if (!params.nonce) {
return { valid: false, message: "'nonce' is required" };
}
if (params.nonce.length < 8) {
return { valid: false, message: "'nonce' must be at least 8 characters" };
}
if (!SIWE_NONCE_REGEX.test(params.nonce)) {
return {
valid: false,
message: "'nonce' must be alphanumeric (letters and numbers only)"
};
}
if (params.statement && params.statement.includes("\n")) {
return { valid: false, message: "'statement' must not contain newlines" };
}
if (params.expirationTime && new Date(params.expirationTime) < /* @__PURE__ */ new Date()) {
return { valid: false, message: "'expirationTime' must be in the future" };
}
if (params.expirationTime && new Date(params.expirationTime) > new Date(Date.now() + 7 * 24 * 60 * 60 * 1e3)) {
return { valid: false, message: "'expirationTime' must be within 7 days" };
}
if (params.notBefore && new Date(params.notBefore) > new Date(Date.now() + 7 * 24 * 60 * 60 * 1e3)) {
return { valid: false, message: "'notBefore' must be within 7 days" };
}
return { valid: true };
};
// src/commands/wallet-auth/index.ts
async function walletAuth(options, ctx) {
const fallbackAdapter = getFallbackAdapter();
const result = await executeWithFallback({
command: "wallet-auth" /* WalletAuth */,
nativeExecutor: () => nativeWalletAuth(options, ctx),
wagmiFallback: fallbackAdapter?.walletAuth ? () => fallbackAdapter.walletAuth({
nonce: options.nonce,
statement: options.statement,
expirationTime: options.expirationTime
}) : void 0,
customFallback: options.fallback
});
if (result.executedWith === "fallback") {
return { executedWith: "fallback", data: result.data };
}
if (result.executedWith === "wagmi") {
return {
executedWith: "wagmi",
data: result.data
};
}
return {
executedWith: "minikit",
data: result.data
};
}
async function nativeWalletAuth(options, ctx) {
if (!ctx) {
ctx = { events: new EventManager(), state: { deviceProperties: {} } };
}
if (typeof window === "undefined" || !isCommandAvailable("wallet-auth" /* WalletAuth */)) {
throw new Error(
"'walletAuth' command is unavailable. Check MiniKit.install() or update the app version"
);
}
const input = {
nonce: options.nonce,
statement: options.statement,
requestId: options.requestId,
expirationTime: options.expirationTime,
notBefore: options.notBefore
};
const validationResult = validateWalletAuthCommandInput(input);
if (!validationResult.valid) {
throw new Error(`Invalid wallet auth input: ${validationResult.message}`);
}
let protocol;
try {
const currentUrl = new URL(window.location.href);
protocol = currentUrl.protocol.split(":")[0];
} catch (error) {
throw new Error("Failed to get current URL");
}
const siweMessage = generateSiweMessage({
scheme: protocol,
domain: window.location.host,
statement: input.statement ?? void 0,
uri: window.location.href,
version: "1",
chain_id: 480,
nonce: input.nonce,
issued_at: (/* @__PURE__ */ new Date()).toISOString(),
expiration_time: input.expirationTime?.toISOString() ?? void 0,
not_before: input.notBefore?.toISOString() ?? void 0,
request_id: input.requestId ?? void 0
});
const walletAuthPayload = { siweMessage };
const worldAppVersion = ctx.state.deviceProperties.worldAppVersion;
if (worldAppVersion && worldAppVersion <= 2087900) {
throw new Error(
"Wallet auth v1 is no longer supported. Please update World App to the latest version."
);
}
const finalPayload = await new Promise(
(resolve, reject) => {
try {
ctx.events.subscribe("miniapp-wallet-auth" /* MiniAppWalletAuth */, (response) => {
ctx.events.unsubscribe("miniapp-wallet-auth" /* MiniAppWalletAuth */);
resolve(response);
});
sendMiniKitEvent({
command: "wallet-auth" /* WalletAuth */,
version: COMMAND_VERSIONS["wallet-auth" /* WalletAuth */],
payload: walletAuthPayload
});
} catch (error) {
reject(error);
}
}
);
if (finalPayload.status === "error") {
throw new WalletAuthError(finalPayload.error_code, finalPayload.details);
}
return {
address: finalPayload.address,
message: finalPayload.message,
signature: finalPayload.signature,
version: finalPayload.version
};
}
// src/helpers/microphone.ts
var microphoneSetupDone = false;
var setupMicrophone = () => {
if (microphoneSetupDone) {
return;
}
if (typeof navigator !== "undefined" && !navigator.mediaDevices?.getUserMedia)
return;
const originalStop = MediaStreamTrack.prototype.stop;
MediaStreamTrack.prototype.stop = function() {
originalStop.call(this);
if (this.readyState === "ended") {
setTimeout(() => this.dispatchEvent(new Event("ended")), 0);
}
};
const realGUM = navigator.mediaDevices.getUserMedia.bind(
navigator.mediaDevices
);
const live = /* @__PURE__ */ new Set();
async function wrapped(constraints) {
const stream = await realGUM(constraints);
const hasAudioTrack = stream.getAudioTracks().length > 0;
if (hasAudioTrack) {
sendMiniKitEvent({
command: "microphone-stream-started",
version: 1,
payload: {
streamId: stream.id
}
});
live.add(stream);
stream.getAudioTracks().forEach((t) => {
t.addEventListener("ended", () => {
const allAudioTracksEnded = stream.getAudioTracks().every((track) => track.readyState === "ended");
if (allAudioTracksEnded) {
sendMiniKitEvent({
command: "microphone-stream-ended",
version: 1,
payload: {
streamId: stream.id
}
});
live.delete(stream);
}
});
});
}
return stream;
}
Object.defineProperty(navigator.mediaDevices, "getUserMedia", {
value: wrapped,
writable: false,
configurable: false,
enumerable: true
});
Object.freeze(navigator.mediaDevices);
const stopAllMiniAppMicrophoneStreams = () => {
live.forEach((s) => {
const audioTracks = s.getAudioTracks();
if (audioTracks.length > 0) {
audioTracks.forEach((t) => {
t.stop();
});
sendMiniKitEvent({
command: "microphone-stream-ended",
version: 1,
payload: {
streamId: s.id
}
});
}
});
live.clear();
};
MiniKit.subscribe("miniapp-microphone" /* MiniAppMicrophone */, (payload) => {
if (payload.status === "error" && (payload.error_code === "mini_app_permission_not_enabled" /* MiniAppPermissionNotEnabled */ || payload.error_code === "world_app_permission_not_enabled" /* WorldAppPermissionNotEnabled */)) {
console.log("stopping all microphone streams", payload);
stopAllMiniAppMicrophoneStreams();
}
});
window.__stopAllMiniAppMicrophoneStreams = stopAllMiniAppMicrophoneStreams;
microphoneSetupDone = true;
};
// src/helpers/usernames.ts
var getUserProfile = async (address) => {
const res = await fetch("https://usernames.worldcoin.org/api/v1/query", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
addresses: [address]
})
});
const usernames = await res.json();
return usernames?.[0] ?? { username: null, profile_picture_url: null };
};
// src/types.ts
var MiniKitInstallErrorMessage = {
["unknown" /* Unknown */]: "Failed to install MiniKit.",
["already_installed" /* AlreadyInstalled */]: "MiniKit is already installed.",
["outside_of_worldapp" /* OutsideOfWorldApp */]: "MiniApp launched outside of WorldApp.",
["not_on_client" /* NotOnClient */]: "Window object is not available.",
["app_out_of_date" /* AppOutOfDate */]: "WorldApp is out of date. Please update the app."
};
// src/minikit.ts
var MINIKIT_VERSION = 1;
var MINIKIT_MINOR_VERSION = 96;
var WORLD_APP_LAUNCH_LOCATION_MAP = {
"app-store": "app-store" /* AppStore */,
carousel: "app-store" /* AppStore */,
explore: "app-store" /* AppStore */,
app_details: "app-store" /* AppStore */,
deeplink: "deep-link" /* DeepLink */,
homepage: "home" /* Home */,
wallet_tab: "wallet-tab" /* WalletTab */,
world_chat: "chat" /* Chat */
};
function mapWorldAppLaunchLocation(location) {
if (!location) return null;
const raw = typeof location === "object" && "open_origin" in location ? location.open_origin : typeof location === "string" ? location : null;
if (!raw) return null;
console.log("MiniKit launch location mapped:", raw);
return WORLD_APP_LAUNCH_LOCATION_MAP[raw.toLowerCase()] ?? null;
}
var _MiniKit = class _MiniKit {
static getActiveMiniKit() {
if (typeof window === "undefined") return this;
const candidate = window.MiniKit;
if (candidate && typeof candidate.trigger === "function") {
return candidate;
}
return this;
}
// ============================================================================
// Unified API (auto-detects environment)
// ============================================================================
/**
* Authenticate user via wallet signature (SIWE)
*
* Works in World App (native SIWE) and web (Wagmi + SIWE fallback).
*
* @example
* ```typescript
* const result = await MiniKit.walletAuth({ nonce: 'randomnonce123' });
* console.log(result.data.address);
* console.log(result.executedWith); // 'minikit' | 'wagmi' | 'fallback'
* ```
*/
static walletAuth(options) {
const active = this.getActiveMiniKit();
if (active !== this) {
return active.walletAuth(options);
}
return walletAuth(options, this.getContext());
}
/**
* Send one or more transactions
*
* World App: batch + permit2 + gas sponsorship
* Web: sequential execut