@worldcoin/minikit-js
Version:
minikit-js is our SDK for building mini-apps.
1,512 lines (1,480 loc) • 52.7 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);
// 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");
// helpers/send-webview-event.ts
var sendWebviewEvent = (payload) => {
if (window.webkit) {
window.webkit?.messageHandlers?.minikit?.postMessage?.(payload);
} else if (window.Android) {
window.Android.postMessage?.(JSON.stringify(payload));
}
};
// commands/types.ts
var COMMAND_VERSIONS = {
["verify" /* Verify */]: 1,
["pay" /* Pay */]: 1,
["wallet-auth" /* WalletAuth */]: 2,
["send-transaction" /* SendTransaction */]: 1,
["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,
["attestation" /* Attestation */]: 1,
["close-miniapp" /* CloseMiniApp */]: 1
};
var commandAvailability = {
["verify" /* Verify */]: 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,
["attestation" /* Attestation */]: false,
["close-miniapp" /* CloseMiniApp */]: false
};
function isCommandAvailable(command) {
return commandAvailability[command];
}
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) {
sendWebviewEvent(payload);
}
// commands/attestation.ts
function createAttestationCommand(_ctx) {
return (input) => {
if (typeof window === "undefined" || !isCommandAvailable("attestation" /* Attestation */)) {
console.error(
"'attestation' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
if (!input.requestHash || input.requestHash.length === 0) {
console.error("'attestation' command requires a non-empty requestHash");
return null;
}
const payload = {
request_hash: input.requestHash
};
sendMiniKitEvent({
command: "attestation" /* Attestation */,
version: COMMAND_VERSIONS["attestation" /* Attestation */],
payload
});
return payload;
};
}
function createAttestationAsyncCommand(ctx, syncCommand) {
return async (input) => {
return new Promise((resolve, reject) => {
try {
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-attestation" /* MiniAppAttestation */);
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe(
"miniapp-attestation" /* MiniAppAttestation */,
handleResponse
);
const commandPayload = syncCommand(input);
if (!commandPayload) {
ctx.events.unsubscribe("miniapp-attestation" /* MiniAppAttestation */);
reject(
new Error(
"'attestation' command failed: command unavailable or invalid input"
)
);
}
} catch (error) {
ctx.events.unsubscribe("miniapp-attestation" /* MiniAppAttestation */);
reject(error);
}
});
};
}
// commands/chat.ts
function createChatCommand(_ctx) {
return (payload) => {
if (typeof window === "undefined" || !isCommandAvailable("chat" /* Chat */)) {
console.error(
"'chat' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
if (payload.message.length === 0) {
console.error("'chat' command requires a non-empty message");
return null;
}
sendMiniKitEvent({
command: "chat" /* Chat */,
version: COMMAND_VERSIONS["chat" /* Chat */],
payload
});
return payload;
};
}
function createChatAsyncCommand(ctx, syncCommand) {
return async (payload) => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-chat" /* MiniAppChat */);
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe("miniapp-chat" /* MiniAppChat */, handleResponse);
commandPayload = syncCommand(payload);
} catch (error) {
reject(error);
}
});
};
}
// commands/close-miniapp.ts
function createCloseMiniAppCommand(_ctx) {
return () => {
if (typeof window === "undefined" || !isCommandAvailable("close-miniapp" /* CloseMiniApp */)) {
console.error(
"'closeMiniApp' command is unavailable. Check MiniKit.install() or update the app version"
);
return false;
}
sendMiniKitEvent({
command: "close-miniapp" /* CloseMiniApp */,
version: COMMAND_VERSIONS["close-miniapp" /* CloseMiniApp */],
payload: {}
});
return true;
};
}
// commands/get-permissions.ts
function createGetPermissionsCommand(_ctx) {
return () => {
if (typeof window === "undefined" || !isCommandAvailable("get-permissions" /* GetPermissions */)) {
console.error(
"'getPermissions' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
sendMiniKitEvent({
command: "get-permissions" /* GetPermissions */,
version: COMMAND_VERSIONS["get-permissions" /* GetPermissions */],
payload: {}
});
return {
status: "sent"
};
};
}
function createGetPermissionsAsyncCommand(ctx, syncCommand) {
return async () => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = (payload) => {
ctx.events.unsubscribe("miniapp-get-permissions" /* MiniAppGetPermissions */);
resolve({ commandPayload, finalPayload: payload });
};
ctx.events.subscribe(
"miniapp-get-permissions" /* MiniAppGetPermissions */,
handleResponse
);
commandPayload = syncCommand();
} catch (error) {
reject(error);
}
});
};
}
// helpers/payment/client.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;
};
// commands/pay.ts
function createPayCommand(_ctx) {
return (payload) => {
if (typeof window === "undefined" || !isCommandAvailable("pay" /* Pay */)) {
console.error(
"'pay' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
if (!validatePaymentPayload(payload)) {
return null;
}
const eventPayload = {
...payload,
network: "worldchain" /* WorldChain */
};
sendMiniKitEvent({
command: "pay" /* Pay */,
version: COMMAND_VERSIONS["pay" /* Pay */],
payload: eventPayload
});
return eventPayload;
};
}
function createPayAsyncCommand(ctx, syncCommand) {
return async (payload) => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-payment" /* MiniAppPayment */);
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe(
"miniapp-payment" /* MiniAppPayment */,
handleResponse
);
commandPayload = syncCommand(payload);
} catch (error) {
reject(error);
}
});
};
}
// commands/request-permission.ts
function createRequestPermissionCommand(_ctx) {
return (payload) => {
if (typeof window === "undefined" || !isCommandAvailable("request-permission" /* RequestPermission */)) {
console.error(
"'requestPermission' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
sendMiniKitEvent({
command: "request-permission" /* RequestPermission */,
version: COMMAND_VERSIONS["request-permission" /* RequestPermission */],
payload
});
return payload;
};
}
function createRequestPermissionAsyncCommand(ctx, syncCommand) {
return async (payload) => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-request-permission" /* MiniAppRequestPermission */);
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe(
"miniapp-request-permission" /* MiniAppRequestPermission */,
handleResponse
);
commandPayload = syncCommand(payload);
} catch (error) {
reject(error);
}
});
};
}
// commands/send-haptic-feedback.ts
function createSendHapticFeedbackCommand(_ctx) {
return (payload) => {
if (typeof window === "undefined" || !isCommandAvailable("send-haptic-feedback" /* SendHapticFeedback */)) {
console.error(
"'sendHapticFeedback' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
sendMiniKitEvent({
command: "send-haptic-feedback" /* SendHapticFeedback */,
version: COMMAND_VERSIONS["send-haptic-feedback" /* SendHapticFeedback */],
payload
});
return payload;
};
}
function createSendHapticFeedbackAsyncCommand(ctx, syncCommand) {
return async (payload) => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-send-haptic-feedback" /* MiniAppSendHapticFeedback */);
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe(
"miniapp-send-haptic-feedback" /* MiniAppSendHapticFeedback */,
handleResponse
);
commandPayload = syncCommand(payload);
} catch (error) {
reject(error);
}
});
};
}
// helpers/transaction/validate-payload.ts
var isValidHex = (str) => {
return /^0x[0-9A-Fa-f]+$/.test(str);
};
var objectValuesToArrayRecursive = (input) => {
if (input === null || typeof input !== "object") {
return input;
}
if (Array.isArray(input)) {
return input.map((item) => objectValuesToArrayRecursive(item));
}
const values = Object.values(input);
return values.map((value) => objectValuesToArrayRecursive(value));
};
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 ("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)) {
result[key] = processPayload(result[key]);
}
}
return result;
}
return payload;
};
var validateSendTransactionPayload = (payload) => {
if (payload.formatPayload) {
const formattedPayload = processPayload(payload);
formattedPayload.transaction = formattedPayload.transaction.map((tx) => {
const args = objectValuesToArrayRecursive(tx.args);
return {
...tx,
args
};
});
return formattedPayload;
}
return payload;
};
// commands/send-transaction.ts
function createSendTransactionCommand(_ctx) {
return (payload) => {
if (typeof window === "undefined" || !isCommandAvailable("send-transaction" /* SendTransaction */)) {
console.error(
"'sendTransaction' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
payload.formatPayload = payload.formatPayload !== false;
const validatedPayload = validateSendTransactionPayload(payload);
sendMiniKitEvent({
command: "send-transaction" /* SendTransaction */,
version: COMMAND_VERSIONS["send-transaction" /* SendTransaction */],
payload: validatedPayload
});
return validatedPayload;
};
}
function createSendTransactionAsyncCommand(ctx, syncCommand) {
return async (payload) => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-send-transaction" /* MiniAppSendTransaction */);
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe(
"miniapp-send-transaction" /* MiniAppSendTransaction */,
handleResponse
);
commandPayload = syncCommand(payload);
} catch (error) {
reject(error);
}
});
};
}
// helpers/share/index.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
};
};
// commands/share.ts
function createShareCommand(ctx) {
return (payload) => {
if (typeof window === "undefined" || !isCommandAvailable("share" /* Share */)) {
console.error(
"'share' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
if (ctx.state.deviceProperties.deviceOS === "ios" && typeof navigator !== "undefined") {
sendMiniKitEvent({
command: "share" /* Share */,
version: COMMAND_VERSIONS["share" /* Share */],
payload
});
navigator.share(payload);
} else {
formatShareInput(payload).then((formattedResult) => {
sendMiniKitEvent({
command: "share" /* Share */,
version: COMMAND_VERSIONS["share" /* Share */],
payload: formattedResult
});
}).catch((error) => {
console.error("Failed to format share input", error);
});
ctx.events.subscribe("miniapp-share" /* MiniAppShare */, (response) => {
console.log("Share Response", response);
});
}
return payload;
};
}
function createShareAsyncCommand(ctx, syncCommand) {
return async (payload) => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-share" /* MiniAppShare */);
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe("miniapp-share" /* MiniAppShare */, handleResponse);
commandPayload = syncCommand(payload);
} catch (error) {
reject(error);
}
});
};
}
// commands/share-contacts.ts
function createShareContactsCommand(_ctx) {
return (payload) => {
if (typeof window === "undefined" || !isCommandAvailable("share-contacts" /* ShareContacts */)) {
console.error(
"'shareContacts' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
sendMiniKitEvent({
command: "share-contacts" /* ShareContacts */,
version: COMMAND_VERSIONS["share-contacts" /* ShareContacts */],
payload
});
return payload;
};
}
function createShareContactsAsyncCommand(ctx, syncCommand) {
return async (payload) => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-share-contacts" /* MiniAppShareContacts */);
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe(
"miniapp-share-contacts" /* MiniAppShareContacts */,
handleResponse
);
commandPayload = syncCommand(payload);
} catch (error) {
reject(error);
}
});
};
}
// commands/sign-message.ts
function createSignMessageCommand(_ctx) {
return (payload) => {
if (typeof window === "undefined" || !isCommandAvailable("sign-message" /* SignMessage */)) {
console.error(
"'signMessage' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
sendMiniKitEvent({
command: "sign-message" /* SignMessage */,
version: COMMAND_VERSIONS["sign-message" /* SignMessage */],
payload
});
return payload;
};
}
function createSignMessageAsyncCommand(ctx, syncCommand) {
return async (payload) => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-sign-message" /* MiniAppSignMessage */);
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe(
"miniapp-sign-message" /* MiniAppSignMessage */,
handleResponse
);
commandPayload = syncCommand(payload);
} catch (error) {
reject(error);
}
});
};
}
// commands/sign-typed-data.ts
function createSignTypedDataCommand(_ctx) {
return (payload) => {
console.warn(
"signTypedData is deprecated. Use signMessage or sendTransaction instead."
);
if (typeof window === "undefined" || !isCommandAvailable("sign-typed-data" /* SignTypedData */)) {
console.error(
"'signTypedData' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
if (!payload.chainId) {
payload.chainId = 480;
}
sendMiniKitEvent({
command: "sign-typed-data" /* SignTypedData */,
version: COMMAND_VERSIONS["sign-typed-data" /* SignTypedData */],
payload
});
return payload;
};
}
function createSignTypedDataAsyncCommand(ctx, syncCommand) {
return async (payload) => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-sign-typed-data" /* MiniAppSignTypedData */);
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe(
"miniapp-sign-typed-data" /* MiniAppSignTypedData */,
handleResponse
);
commandPayload = syncCommand(payload);
} catch (error) {
reject(error);
}
});
};
}
// commands/verify.ts
var import_idkit_core = require("@worldcoin/idkit-core");
var import_hashing = require("@worldcoin/idkit-core/hashing");
var import_idkit_core2 = require("@worldcoin/idkit-core");
function createVerifyCommand(ctx) {
return (payload) => {
if (typeof window === "undefined" || !isCommandAvailable("verify" /* Verify */)) {
console.error(
"'verify' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
if (Array.isArray(payload.verification_level) && payload.verification_level.length === 0) {
console.error("'verification_level' must not be an empty array");
return null;
}
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
const eventPayload = {
action: (0, import_hashing.encodeAction)(payload.action),
signal: (0, import_hashing.generateSignal)(payload.signal).digest,
verification_level: payload.verification_level || import_idkit_core.VerificationLevel.Orb,
timestamp
};
ctx.events.setVerifyActionProcessingOptions({
skip_proof_compression: payload.skip_proof_compression
});
sendMiniKitEvent({
command: "verify" /* Verify */,
version: COMMAND_VERSIONS["verify" /* Verify */],
payload: eventPayload
});
return eventPayload;
};
}
function createVerifyAsyncCommand(ctx, syncCommand) {
let hasInFlightVerifyRequest = false;
return async (payload) => {
if (hasInFlightVerifyRequest) {
return Promise.reject(
new Error(
"A verify request is already in flight. Wait for the current request to complete before sending another."
)
);
}
return new Promise((resolve, reject) => {
try {
hasInFlightVerifyRequest = true;
let commandPayload = null;
const handleResponse = (response) => {
ctx.events.unsubscribe("miniapp-verify-action" /* MiniAppVerifyAction */);
hasInFlightVerifyRequest = false;
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe(
"miniapp-verify-action" /* MiniAppVerifyAction */,
handleResponse
);
commandPayload = syncCommand(payload);
if (commandPayload === null) {
ctx.events.unsubscribe("miniapp-verify-action" /* MiniAppVerifyAction */);
hasInFlightVerifyRequest = false;
reject(
new Error(
"Failed to send verify command. Ensure MiniKit is installed and the verify command is available."
)
);
}
} catch (error) {
hasInFlightVerifyRequest = false;
reject(error);
}
});
};
}
// helpers/siwe/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;
};
// helpers/siwe/validate-wallet-auth-command-input.ts
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 (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 };
};
// commands/wallet-auth.ts
function createWalletAuthCommand(ctx) {
return (payload) => {
if (typeof window === "undefined" || !isCommandAvailable("wallet-auth" /* WalletAuth */)) {
console.error(
"'walletAuth' command is unavailable. Check MiniKit.install() or update the app version"
);
return null;
}
const validationResult = validateWalletAuthCommandInput(payload);
if (!validationResult.valid) {
console.error(
"Failed to validate wallet auth input:\n\n -->",
validationResult.message
);
return null;
}
let protocol = null;
try {
const currentUrl = new URL(window.location.href);
protocol = currentUrl.protocol.split(":")[0];
} catch (error) {
console.error("Failed to get current URL", error);
return null;
}
const siweMessage = generateSiweMessage({
scheme: protocol,
domain: window.location.host,
statement: payload.statement ?? void 0,
uri: window.location.href,
version: "1",
chain_id: 480,
nonce: payload.nonce,
issued_at: (/* @__PURE__ */ new Date()).toISOString(),
expiration_time: payload.expirationTime?.toISOString() ?? void 0,
not_before: payload.notBefore?.toISOString() ?? void 0,
request_id: payload.requestId ?? void 0
});
const walletAuthPayload = { siweMessage };
const walletAuthVersion = ctx.state.user.worldAppVersion && ctx.state.user.worldAppVersion > 2087900 ? COMMAND_VERSIONS["wallet-auth" /* WalletAuth */] : 1;
sendMiniKitEvent({
command: "wallet-auth" /* WalletAuth */,
version: walletAuthVersion,
payload: walletAuthPayload
});
return walletAuthPayload;
};
}
function createWalletAuthAsyncCommand(ctx, syncCommand) {
return async (payload) => {
return new Promise((resolve, reject) => {
try {
let commandPayload = null;
const handleResponse = async (response) => {
ctx.events.unsubscribe("miniapp-wallet-auth" /* MiniAppWalletAuth */);
if (response.status === "success") {
await ctx.state.updateUserFromWalletAuth(response.address);
}
resolve({ commandPayload, finalPayload: response });
};
ctx.events.subscribe(
"miniapp-wallet-auth" /* MiniAppWalletAuth */,
handleResponse
);
commandPayload = syncCommand(payload);
} catch (error) {
reject(error);
}
});
};
}
// commands/index.ts
function createCommands(ctx) {
return {
verify: createVerifyCommand(ctx),
pay: createPayCommand(ctx),
walletAuth: createWalletAuthCommand(ctx),
sendTransaction: createSendTransactionCommand(ctx),
signMessage: createSignMessageCommand(ctx),
/** @deprecated EIP-712 typed data signing is deprecated. Use signMessage or sendTransaction instead. */
signTypedData: createSignTypedDataCommand(ctx),
shareContacts: createShareContactsCommand(ctx),
requestPermission: createRequestPermissionCommand(ctx),
getPermissions: createGetPermissionsCommand(ctx),
sendHapticFeedback: createSendHapticFeedbackCommand(ctx),
share: createShareCommand(ctx),
chat: createChatCommand(ctx),
attestation: createAttestationCommand(ctx),
closeMiniApp: createCloseMiniAppCommand(ctx)
};
}
function createAsyncCommands(ctx, commands) {
return {
verify: createVerifyAsyncCommand(ctx, commands.verify),
pay: createPayAsyncCommand(ctx, commands.pay),
walletAuth: createWalletAuthAsyncCommand(ctx, commands.walletAuth),
sendTransaction: createSendTransactionAsyncCommand(
ctx,
commands.sendTransaction
),
signMessage: createSignMessageAsyncCommand(ctx, commands.signMessage),
/** @deprecated EIP-712 typed data signing is deprecated. Use signMessage or sendTransaction instead. */
signTypedData: createSignTypedDataAsyncCommand(ctx, commands.signTypedData),
shareContacts: createShareContactsAsyncCommand(ctx, commands.shareContacts),
requestPermission: createRequestPermissionAsyncCommand(
ctx,
commands.requestPermission
),
getPermissions: createGetPermissionsAsyncCommand(
ctx,
commands.getPermissions
),
sendHapticFeedback: createSendHapticFeedbackAsyncCommand(
ctx,
commands.sendHapticFeedback
),
share: createShareAsyncCommand(ctx, commands.share),
chat: createChatAsyncCommand(ctx, commands.chat),
attestation: createAttestationAsyncCommand(ctx, commands.attestation)
};
}
// core/events.ts
var import_idkit_core3 = require("@worldcoin/idkit-core");
// helpers/proof/index.ts
var import_viem2 = require("viem");
var import_chains2 = require("viem/chains");
var semaphoreVerifierAddress = "0x79f46b94d134109EbcbbddBAeD0E88790409A0e4";
var semaphoreVerifierAbi = [
{
inputs: [
{
internalType: "uint256[8]",
name: "proof",
type: "uint256[8]"
}
],
name: "compressProof",
outputs: [
{
internalType: "uint256[4]",
name: "compressed",
type: "uint256[4]"
}
],
stateMutability: "view",
type: "function"
}
];
var compressAndPadProof = async (proof, rpcUrl) => {
try {
const publicClient = (0, import_viem2.createPublicClient)({
chain: import_chains2.worldchain,
transport: (0, import_viem2.http)(
rpcUrl || "https://worldchain-mainnet.g.alchemy.com/public"
)
});
const decodedProof = (0, import_viem2.decodeAbiParameters)(
[{ type: "uint256[8]" }],
proof
)[0];
const compressedProof = await publicClient.readContract({
address: semaphoreVerifierAddress,
abi: semaphoreVerifierAbi,
functionName: "compressProof",
args: [decodedProof]
});
const paddedProof = [...compressedProof, 0n, 0n, 0n, 0n];
return (0, import_viem2.encodeAbiParameters)([{ type: "uint256[8]" }], [paddedProof]);
} catch (e) {
return proof;
}
};
// core/events.ts
var EventManager = class {
constructor() {
this.listeners = {
["miniapp-verify-action" /* MiniAppVerifyAction */]: () => {
},
["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 */]: () => {
},
["miniapp-attestation" /* MiniAppAttestation */]: () => {
}
};
this.verifyActionProcessingOptionsQueue = [];
}
subscribe(event, handler) {
this.listeners[event] = handler;
}
unsubscribe(event) {
delete this.listeners[event];
}
setVerifyActionProcessingOptions(options) {
this.verifyActionProcessingOptionsQueue.push({
skip_proof_compression: Boolean(options?.skip_proof_compression ?? false)
});
}
trigger(event, payload) {
if (!this.listeners[event]) {
console.error(
`No handler for event ${event}, payload: ${JSON.stringify(payload)}`
);
return;
}
if (event === "miniapp-verify-action" /* MiniAppVerifyAction */) {
const handler = this.listeners[event];
const processingOptions = this.verifyActionProcessingOptionsQueue.shift() ?? {
skip_proof_compression: false
};
this.processVerifyActionPayload(
payload,
handler,
processingOptions
);
return;
}
this.listeners[event](payload);
}
async processVerifyActionPayload(payload, handler, processingOptions) {
if (payload.status === "error" && payload.error_code === "user_rejected") {
payload.error_code = import_idkit_core3.AppErrorCodes.VerificationRejected;
}
if (payload.status === "success" && !processingOptions.skip_proof_compression) {
if ("verifications" in payload) {
const orbVerification = payload.verifications.find(
(v) => v.verification_level === import_idkit_core3.VerificationLevel.Orb
);
if (orbVerification) {
orbVerification.proof = await this.compressProofSafely(
orbVerification.proof,
{
mode: "multi",
payloadVersion: payload.version,
verificationsCount: payload.verifications.length,
verificationLevel: orbVerification.verification_level
}
);
}
} else if (payload.verification_level === import_idkit_core3.VerificationLevel.Orb) {
payload.proof = await this.compressProofSafely(
payload.proof,
{
mode: "single",
payloadVersion: payload.version,
verificationLevel: payload.verification_level
}
);
}
}
handler(payload);
}
async compressProofSafely(proof, context) {
try {
return await compressAndPadProof(proof);
} catch (error) {
console.error(
"Failed to compress verification proof. Delivering payload with uncompressed proof.",
{
...context,
error
}
);
return proof;
}
}
};
// helpers/usernames/index.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 };
};
// types/init.ts
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 */
};
var mapWorldAppLaunchLocation = (location) => {
if (!location || typeof location !== "string") return null;
console.log("MiniKit launch location mapped:", location);
const normalizedLocation = location.toLowerCase();
return WORLD_APP_LAUNCH_LOCATION_MAP[normalizedLocation] ?? null;
};
// core/state.ts
var MiniKitState = class {
constructor() {
this.appId = null;
this.user = {};
this.deviceProperties = {};
this.location = null;
this.isReady = false;
}
initFromWorldApp(worldApp) {
if (!worldApp) return;
this.user.optedIntoOptionalAnalytics = worldApp.is_optional_analytics;
this.user.preferredCurrency = worldApp.preferred_currency;
this.user.deviceOS = worldApp.device_os;
this.user.worldAppVersion = worldApp.world_app_version;
this.deviceProperties.safeAreaInsets = worldApp.safe_area_insets;
this.deviceProperties.deviceOS = worldApp.device_os;
this.deviceProperties.worldAppVersion = worldApp.world_app_version;
this.location = mapWorldAppLaunchLocation(worldApp.location);
}
async updateUserFromWalletAuth(address) {
this.user.walletAddress = address;
try {
const userProfile = await getUserProfile(address);
this.user.username = userProfile.username;
this.user.profilePictureUrl = userProfile.profile_picture_url;
} catch (error) {
console.error("Failed to fetch user profile:", error);
}
}
async getUserByAddress(address) {
const walletAddress = address ?? this.user.walletAddress;
const userProfile = await getUserProfile(walletAddress);
return {
walletAddress,
username: userProfile.username,
profilePictureUrl: userProfile.profile_picture_url
};
}
async getUserByUsername(username) {
const res = await fetch(
`https://usernames.worldcoin.org/api/v1/${username}`,
{
method: "GET",
headers: {
"Content-Type": "application/json"
}
}
);
const user = await res.json();
return {
walletAddress: user.address,
username: user.username,
profilePictureUrl: user.profile_picture_url
};
}
};
// types/errors.ts
var import_idkit_core4 = require("@worldcoin/idkit-core");
var import_idkit_core5 = require("@worldcoin/idkit-core");
var VerificationErrorMessage = {
[import_idkit_core4.AppErrorCodes.VerificationRejected]: "You've cancelled the request in World App.",
[import_idkit_core4.AppErrorCodes.MaxVerificationsReached]: "You have already verified the maximum number of times for this action.",
[import_idkit_core4.AppErrorCodes.CredentialUnavailable]: "It seems you do not have the verification level required by this app.",
[import_idkit_core4.AppErrorCodes.MalformedRequest]: "There was a problem with this request. Please try again or contact the app owner.",
[import_idkit_core4.AppErrorCodes.InvalidNetwork]: "Invalid network. If you are the app owner, visit docs.worldcoin.org/test for details.",
[import_idkit_core4.AppErrorCodes.InclusionProofFailed]: "There was an issue fetching your credential. Please try again.",
[import_idkit_core4.AppErrorCodes.InclusionProofPending]: "Your identity is still being registered. Please wait a few minutes and try again.",
[import_idkit_core4.AppErrorCodes.UnexpectedResponse]: "Unexpected response from your wallet. Please try again.",
[import_idkit_core4.AppErrorCodes.FailedByHostApp]: "Verification failed by the app. Please contact the app owner for details.",
[import_idkit_core4.AppErrorCodes.GenericError]: "Something unexpected went wrong. Please try again.",
[import_idkit_core4.AppErrorCodes.ConnectionFailed]: "Connection to your wallet failed. Please try again."
};
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."
};
// helpers/microphone/index.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) {
sendWebviewEvent({
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) {
sendWebviewEvent({
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();
});
sendWebviewEvent({
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;
};
// minikit.ts
var MINIKIT_VERSION = 1;
var MINIKIT_MINOR_VERSION = 96;
var _MiniKit = class _MiniKit {
// ============================================================================
// Public State Accessors
// ============================================================================
static get appId() {
return this.stateManager.appId;
}
static set appId(value) {
this.stateManager.appId = value;
}
static get user() {
return this.stateManager.user;
}
static set user(value) {
this.stateManager.user = value;
}
static get deviceProperties() {
return this.stateManager.deviceProperties;
}
static get location() {
return this.stateManager.location;
}
// ============================================================================
// Event System
// ============================================================================
static subscribe(event, handler) {
if (event === "miniapp-wallet-auth" /* MiniAppWalletAuth */) {
const originalHandler = handler;
const wrappedHandler = async (payload) => {
if (payload.status === "success") {
await this.stateManager.updateUserFromWalletAuth(payload.address);
}
originalHandler(payload);
};
this.eventManager.subscribe(event, wrappedHandler);
} else {
this.eventManager.subscribe(event, handler);
}
}
static unsubscribe(event) {
this.eventManager.unsubscribe(event);
}
static trigger(event, payload) {
this.eventManager.trigger(event, payload);
}
// ============================================================================
// Installation
// ============================================================================
static sendInit() {
sendWebviewEvent({
command: "init",
payload: {
version: MINIKIT_VERSION,
minorVersion: MINIKIT_MINOR_VERSION
}
});
}
static install(appId) {
if (typeof window === "undefined" || Boolean(window.MiniKit)) {
return {
success: false,
errorCode: "already_installed" /* AlreadyInstalled */,
errorMessage: MiniKitInstallErrorMessage["already_installed" /* AlreadyInstalled */]
};
}
if (!appId) {
console.warn("App ID not provided during install");
} else {
this.stateManager.appId = appId;
}
if (!window.WorldApp) {
return {
success: false,
errorCode: "outside_of_worldapp" /* OutsideOfWorldApp */,
errorMessage: MiniKitInstallErrorMessage["outside_of_worldapp" /* OutsideOfWorldApp */]
};
}
this.stateManager.initFromWorldApp(window.WorldApp);
try {
window.MiniKit = _MiniKit;
this.sendInit();
} catch (error) {
console.error(
MiniKitInstallErrorMessage["unknown" /* Unknown */],
error
);
return {
success: false,
errorCode: "unknown" /* Unknown */,
errorMessage: MiniKitInstallErrorMessage["unknown" /* Unknown */]
};
}
this.stateManager.isReady = true;
setupMicrophone();
if (!validateCommands(window.WorldApp.supported_commands)) {
return {
success: false,
errorCode: "app_out_of_date" /* AppOutOfDate */,
errorMessage: MiniKitInstallErrorMessage["app_out_of_date" /* AppOutOfDate */]
};
}
return { success: true };
}
static isInstalled(debug) {
const isInstalled = this.stateManager.isReady && Boolean(window.MiniKit);
if (!isInstalled) {
console.error(
"MiniKit is not installed. Make sure you're running the application inside of World App"
);
}
if (debug && isInstalled) {
console.log("MiniKit is alive!");
}
return isInstalled;
}
// ============================================================================
// Commands
// ============================================================================
static getContext() {
return {
events: this.eventManager,
state: this.stateManager
};
}
static get commands() {
if (!this.commandsInstance) {
this.commandsInstance = createCommands(this.getContext());
}
return this.commandsInstance;
}
static get